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

如何在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、调整时间参数即可生效。

三、使用说明

  1. 编译所有C++类,在UE4编辑器中刷新项目
  2. 给ABoxActor的材质实例赋值不同贴图,直接在编辑器细节面板完成
  3. 需要巡逻的盒子,在Patrol分类下添加巡逻点坐标,运行后会自动沿点循环移动
  4. 调整GameManager的参数可灵活控制盒子生成频率和存活时间

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:31:17