如何在Unreal Engine 4中无需蓝图按逻辑生成盒子并实现巡逻?
Unreal Engine 4 无蓝图实现盒子生成销毁与巡逻移动方案
一、创建带多贴图切换的盒子Actor
先编写一个C++类ABoxActor(继承自AActor),核心代码如下:
.h 文件
#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "BoxActor.generated.h" UCLASS() class YOURPROJECT_API ABoxActor : public AActor { GENERATED_BODY() public: ABoxActor(); virtual void Tick(float DeltaTime) override; // 切换盒子贴图的函数 UFUNCTION(BlueprintCallable, Category = "Box") void SetBoxTexture(int32 TextureIndex); // 巡逻相关设置 UPROPERTY(EditAnywhere, Category = "Patrol") TArray<FVector> PatrolPoints; UPROPERTY(EditAnywhere, Category = "Patrol") float MoveSpeed = 100.0f; private: UPROPERTY(VisibleAnywhere, Category = "Components") UStaticMeshComponent* BoxMesh; UPROPERTY(EditAnywhere, Category = "Textures") UMaterialInstanceDynamic* Mat_Texture1; UPROPERTY(EditAnywhere, Category = "Textures") UMaterialInstanceDynamic* Mat_Texture2; int32 CurrentPatrolPoint = 0; };
.cpp 文件
#include "BoxActor.h" #include "Components/StaticMeshComponent.h" #include "Kismet/KismetMathLibrary.h" ABoxActor::ABoxActor() { PrimaryActorTick.bCanEverTick = true; BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BoxMesh")); RootComponent = BoxMesh; // 加载默认立方体网格 static ConstructorHelpers::FObjectFinder<UStaticMesh> CubeMesh(TEXT("/Engine/BasicShapes/Cube.Cube")); if (CubeMesh.Succeeded()) { BoxMesh->SetStaticMesh(CubeMesh.Object); } } void ABoxActor::Tick(float DeltaTime) { Super::Tick(DeltaTime); // 巡逻逻辑:仅当巡逻点数量≥2时生效 if (PatrolPoints.Num() < 2) return; FVector TargetPos = PatrolPoints[CurrentPatrolPoint]; FVector MoveDir = (TargetPos - GetActorLocation()).GetSafeNormal(); SetActorLocation(GetActorLocation() + MoveDir * MoveSpeed * DeltaTime); // 到达目标点后切换下一个巡逻点 if (FVector::Dist(GetActorLocation(), TargetPos) < 5.0f) { CurrentPatrolPoint = (CurrentPatrolPoint + 1) % PatrolPoints.Num(); } } void ABoxActor::SetBoxTexture(int32 TextureIndex) { if (TextureIndex == 1 && Mat_Texture1) { BoxMesh->SetMaterial(0, Mat_Texture1); } else if (TextureIndex == 2 && Mat_Texture2) { BoxMesh->SetMaterial(0, Mat_Texture2); } }
编译完成后,在UE编辑器中给Mat_Texture1和Mat_Texture2绑定带不同贴图的材质实例即可。
二、定时定点生成/销毁盒子
编写一个AGameManager类(继承自AActor)来统一管理盒子的生命周期:
.h 文件
#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "GameManager.generated.h" UCLASS() class YOURPROJECT_API AGameManager : public AActor { GENERATED_BODY() public: AGameManager(); virtual void BeginPlay() override; UPROPERTY(EditAnywhere, Category = "Spawn") TArray<FVector> SpawnPositions; UPROPERTY(EditAnywhere, Category = "Spawn") float SpawnInterval = 5.0f; UPROPERTY(EditAnywhere, Category = "Spawn") float DestroyAfter = 10.0f; UPROPERTY(EditAnywhere, Category = "Spawn") TSubclassOf<class ABoxActor> BoxActorClass; private: FTimerHandle SpawnTimer; void SpawnBox(); };
.cpp 文件
#include "GameManager.h" #include "BoxActor.h" #include "Kismet/KismetMathLibrary.h" AGameManager::AGameManager() { PrimaryActorTick.bCanEverTick = false; } void AGameManager::BeginPlay() { Super::BeginPlay(); // 启动定时生成定时器 GetWorldTimerManager().SetTimer(SpawnTimer, this, &AGameManager::SpawnBox, SpawnInterval, true); } void AGameManager::SpawnBox() { if (SpawnPositions.Num() == 0 || !BoxActorClass) return; // 随机选择一个生成点 int32 RandPosIndex = UKismetMathLibrary::RandomIntegerInRange(0, SpawnPositions.Num() - 1); FVector SpawnLoc = SpawnPositions[RandPosIndex]; FRotator SpawnRot = FRotator::ZeroRotator; ABoxActor* NewBox = GetWorld()->SpawnActor<ABoxActor>(BoxActorClass, SpawnLoc, SpawnRot); if (NewBox) { // 随机设置盒子贴图 int32 RandTex = UKismetMathLibrary::RandomIntegerInRange(1, 2); NewBox->SetBoxTexture(RandTex); // 设置盒子自动销毁 GetWorldTimerManager().SetTimerForActor(NewBox, &ABoxActor::Destroy, DestroyAfter, false); } }
将GameManager拖入场景,在细节面板中添加生成坐标、指定BoxActorClass、调整时间参数即可生效。
三、使用说明
- 编译所有C++类,在UE4编辑器中刷新项目
- 给
ABoxActor的材质实例赋值不同贴图,直接在编辑器细节面板完成 - 需要巡逻的盒子,在
Patrol分类下添加巡逻点坐标,运行后会自动沿点循环移动 - 调整
GameManager的参数可灵活控制盒子生成频率和存活时间
内容的提问来源于stack exchange,提问作者appeldaniel
相关产品推荐
相关产品推荐

