You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unreal C++:从其他类修改可生成蓝图变量时编辑器崩溃问题求助

问题根源分析

你的编辑器崩溃完全是因为错误实例化Unreal Actor对象导致的!在Unreal引擎中,所有继承自AActor的类(比如你的ADMProjectile)绝对不能像普通C++对象那样直接用栈实例化(ADMProjectile ProjectileClass;)或者new关键字创建——Unreal的Actor依赖引擎的对象管理系统,必须通过UWorld::SpawnActor()方法生成,而且只有在需要将实体放入游戏世界时才应该创建。

你当前代码里的栈对象ProjectileClass,它的组件(比如CollisionComp、ProjectileMovement)根本没有被引擎初始化,访问它的变量(哪怕是简单的isExplosiveBullets)都会触发内存访问错误,直接导致编辑器崩溃。

另外,你的逻辑也有问题:拾取PowerUp时,玩家还没有发射子弹,此时去操作一个不存在的子弹对象完全没必要。正确的思路是把“爆炸子弹”的状态存储在玩家角色身上,等玩家实际发射子弹时,再根据这个状态设置新生成的子弹属性。


修复方案

步骤1:给玩家角色添加爆炸子弹状态变量

打开你的DMCharacter.h,添加一个跟踪PowerUp状态的布尔变量:

#pragma once
// ... 其他头文件 ...
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "DMCharacter.generated.h"

UCLASS()
class ADM_API ADMCharacter : public ACharacter {
    GENERATED_BODY()

    // ... 其他已有代码 ...

public:
    // ... 其他已有方法 ...

    // 标记玩家是否拥有爆炸子弹Buff
    UPROPERTY(VisibleAnywhere, Category = PowerUps)
    bool bHasExplosiveBullets = false;
};

步骤2:修改PowerUp的重叠触发逻辑

更新ExplosiveBulletPowerUp.cpp中的OnOverlapBegin函数,将状态设置到玩家角色上,而不是操作不存在的子弹:

#include "ExplosiveBulletPowerUp.h"
#include "DM/DMProjectile.h"
#include "DM/DMCharacter.h"

// ... 已有构造函数和BeginPlay ...

void AExplosiveBulletPowerUp::OnOverlapBegin(class AActor* OverlappedActor, class AActor* OtherActor) {
    if (OtherActor->ActorHasTag("player")) {
        // 将重叠对象转换为玩家角色类(安全转换,避免类型错误)
        ADMCharacter* PlayerChar = Cast<ADMCharacter>(OtherActor);
        if (PlayerChar) {
            // 开启玩家的爆炸子弹状态
            PlayerChar->bHasExplosiveBullets = true;
            UE_LOG(LogTemp, Warning, TEXT("玩家获得爆炸子弹Buff!"));
            // 销毁当前PowerUp道具
            OverlappedActor->Destroy();
        }
    }
}

步骤3:在玩家发射子弹时应用状态

找到玩家角色中负责发射子弹的代码(比如Fire()方法),在生成子弹时根据玩家的状态设置isExplosiveBullets:

void ADMCharacter::Fire() {
    // 假设你已经定义了ProjectileClass作为子弹的类模板
    if (ProjectileClass) {
        UWorld* const World = GetWorld();
        if (World) {
            // 获取枪口位置和旋转(根据你的角色Socket调整)
            FVector SpawnLocation = GetMesh()->GetSocketLocation("MuzzleSocket");
            FRotator SpawnRotation = GetControlRotation();

            // 生成子弹(这才是Unreal中创建Actor的正确方式)
            ADMProjectile* Projectile = World->SpawnActor<ADMProjectile>(ProjectileClass, SpawnLocation, SpawnRotation);
            if (Projectile) {
                // 根据玩家当前的Buff状态设置子弹属性
                Projectile->isExplosiveBullets = bHasExplosiveBullets;
                // 可以在这里同步其他属性,比如伤害
                Projectile->WeaponDamage = WeaponDamage;
            }
        }
    }
}

额外优化建议

如果你的PowerUp有持续时间,可以在玩家角色中添加一个计时器,时间结束后自动将bHasExplosiveBullets重置为false:

// 在ADMCharacter的PowerUp获取逻辑中添加计时器
void ADMCharacter::ActivateExplosiveBullets(float Duration) {
    bHasExplosiveBullets = true;
    // 设置延迟回调,时间到了关闭Buff
    GetWorldTimerManager().SetTimer(ExplosiveBulletTimerHandle, this, &ADMCharacter::DeactivateExplosiveBullets, Duration, false);
}

void ADMCharacter::DeactivateExplosiveBullets() {
    bHasExplosiveBullets = false;
    GetWorldTimerManager().ClearTimer(ExplosiveBulletTimerHandle);
}

内容的提问来源于stack exchange,提问作者lajson 22

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 07:27:35