• 实例甜点 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.3UE_4.16EngineSourceRuntimeCorePublicContainers/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

  • 相关阅读:
    如何制作a2sd+
    WinForm/Silverlight多线程编程中如何更新UI控件的值
    c#如何操作cookie
    Windows Mobile CookieContainer
    Microsoft.Practices.EnterpriseLibrary.Data 数据库操作
    获取手机卡imei和imsi信息
    winform 分页控件
    asp.net 导出数据到Excle
    asp.net异步调用
    shell脚本中常用命令
  • 原文地址:https://www.cnblogs.com/JackSamuel/p/7323481.html
Copyright © 2020-2023  润新知