实例甜点 Unreal Engine 4迷你教程(6)之三个重要基础操作SpawnActor、TArray的Add和Remove

本小节的教程需要完成前置教程:建议阅读《实例甜点 Unreal Engine 4迷你教程(5)》,因为5里面提到了本节的工程,不过也可以在不看5的前提下直接阅读本教程。

 

第一步:Empty的工程(C++ Basic Code);

第二步:新建MyActor类;

 

 

 

第三步:新建一个叫做sandActor类:

 

 

 

Tips:我在调试过程中遇到很恶心的事情,就是修改了代码之后发现没有用,这可能是热加载失败的表现,请重新打开UE4VS不用重启)。

 

第四步:

Sand文件不用修改,只需要修改MyActor的文件如下:

 

▼代码开始
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "sand.h"
#include "MyActor.generated.h"


UCLASS()
class EMPTY_API AMyActor : public AActor
{
    GENERATED_BODY()
    
public:    
    // Sets default values for this actor's properties
    AMyActor();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public:    
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    UPROPERTY()
        TArray<Asand* > arr;//【注意最好有UPROPERTY()标注】
    
    
};
▲代码结束

▼代码开始
// Fill out your copyright notice in the Description page of Project Settings.

#include "MyActor.h"


// Sets default values
AMyActor::AMyActor()
{
     // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();
    for (auto i = 0; i < 4; i++)
    {
        Asand* newSand = GetWorld()->SpawnActor<Asand>(Asand::StaticClass());//【SpawnActor的方法】
        arr.Add(newSand);//【Add的方法】
        UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("[log by wenjie] i ve added a sand tinto arr"));//【打印的方法】
    }

}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    static int32 Timer = 0;
    if (Timer++ == 20)
    {
        UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("[log by wenjie] Time==20"));
/*
不正确的方法:
        for (auto i : arr)
        {//【不建议的remove方法】
            arr.Remove(i);
            UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("[log by wenjie] removed one instance"));
    }

上面的remove的方法不十分优雅:
在执行过程中报如下错误【可能死机也可能不死机】:
LogOutputDevice:Error: === Handled ensure: ===
LogOutputDevice:Error: Ensure condition failed: Lhs.CurrentNum == Lhs.InitialNum [File:D:\UE4.16.3\UE_4.16\Engine\Source\Runtime\Core\Public\Containers/Array.h] [Line: 197]
LogOutputDevice:Error: Array has changed during ranged-for iteration!

以下提供恰当的remove方法:
//参考资料:
//https://forums.unrealengine.com/showthread.php?69383-A-Little-Tip-Remove-elements-from-an-array-in-one-pass-with-a-reverse-for-loop
*/
        for (auto i = arr.Num() - 1; i >= 0; i--)
        {
            arr.RemoveAt(i);
            UE_LOG(LogTemp, Warning, TEXT("%s"), *FString("[log by wenjie] removed one instance"));
        }
    }
}

▲代码结束

 

补充说明:不是说remove(实例引用)不对,而是不应该把它和foreachloop搭配,正确的做法是倒序移除。

你看,完全没有红色的报错:

 

 

 

——小江村儿的文杰 zouwj5@qq.com 20178721:50:52

 

posted @ 2017-08-09 09:27  小江村儿的文杰  阅读(1410)  评论(0编辑  收藏  举报