C++ を使ってレベルをロード / アンロードする

C++ で作成したカスタム ストリーミング アクタでレベルをストリームする方法

プレイヤーが角を曲がって中庭に近づいてくる時にはストリーミング レベルがロードされて表示できるように、 ここで中庭レベルにストリーミングを開始します。

StreamingLevelVisible.png

設定対象は SunTemple_PersistentSunTemple_Streaming です。Player StartSunTemple_Persistent にあります。 そしてゲームのプレイヤーは Character で表現されます。

  1. コンテンツ ブラウザ から SunTemple_Persistent を開きます。

  2. Player Start を寺院の一番手前に移動します。

    PlayerStart.png

  3. [Window] をクリックして、[Level] を選択します。

  4. [Levels] のドロップダウン メニューをクリックし、[Add Existing... (既存の...を追加)] を選択して新規サブレベルを追加します。

    AddExisting.png

  5. 追加する SunTemple_Streaming[Open Level] ダイアログで選択してから、[Open] をクリックします。

    SunTempleStreaming_Select.png

  6. パーシスタント レベル 上で 右クリック して、ドロップダウン メニューから [Make Current] を選択します。

C++ を使ってレベルをストリーミングする

  1. コンテンツ ブラウザ を開いて、[C++ Class] を新規作成します。このクラスは アクタ に基づくので、アクタ を選択して [Next (次へ)] をクリックします。

  2. 作成された C++ Class に「LevelStreamerActor」と名前を付けて、[Create Class (クラスを作成)] をクリックします。このクラスを Visual Studio または XCode で開くことができるようになります。

このシナリオの場合、Character が OverlapVolume という Box コンポーネントをオーバーラップしたら、2 つ目のレベルをストリーミングします。

  1. LevelStreamerActor.h で、VisibleAnywhere、BlueprintReadOnly であり、AllowPrivateAccess メタ フラグをもつ OverlapVolume を宣言します。

        private:
        // レベルストリーミングのトリガーとなるオーバーラップボリューム
        UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
        UBoxComponent* OverlapVolume;
  2. LevelStreamerActor.cpp で、LevelStreamerActor コンストラクタの中に、OverlapVolume を作成して RootComponent にします。

        OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume"));
        RootComponent = OverlapVolume;
  3. LevelStreamerActor.h に戻って、protected の OverlapBegins 関数を宣言すると、BoxComponent の OnComponentBeginOverlap 関数に結合します。つまり、OverlapBegins は UFUNCTION マクロでタグ付けされなければならず、OnComponentBeginOverlap と同じシグネチャを持たなければならないという意味です。

        protected:
    
        UFUNCTION()
        void OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
  4. LevelStreamerActor.h で、LevelToLoad を呼び出す EditAnywhere である protected の FName 変数も作成します。これにより、インスタンスごとに LevelToLoad を変更できるようになります。

        UPROPERTY(EditAnywhere)
        FName LevelToLoad;
  5. GameplayStatics ライブラリから幾つか関数を使用して、LevelStreamerActor.cpp にこれが含まれるようにします。

        #include "Kismet/GameplayStatics.h"
  6. OverlapBegins 機能を作成する準備ができました。LevelStreamerActor.cpp で、関数の定義を開始します。Index 0 でキャラクターを取得するために、GameplayStatics 関数 GetPlayerCharacter も使用できます。

        void ALevelStreamerActor::OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
        {
                ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
        }
  7. MyCharacter を取得したら、OtherActor が BoxComponent にオーバーラップしていることを確認します。さらに、LevelToLoad が空でないことを確認したら LoadStreamLevel を呼び出します。

        if (OtherActor == MyCharacter && LevelToLoad != "")
        {
            FLatentActionInfo LatentInfo;
            UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true, LatentInfo);
        }
  8. LevelStreamerActor コンストラクタ で OverlapBegins を BoxComponent の OnComponentBeginOverlap に結合します。

        OverlapVolume->OnComponentBeginOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapBegins);

    LevelStreamerActor.h は最終的にこのようになります。

        #pragma once
    
        #include "GameFramework/Actor.h"
        #include "LevelStreamerActor.generated.h"
    
        UCLASS()
        class LEVELS_API ALevelStreamerActor : public AActor
        {
            GENERATED_BODY()
    
        public:
            // このアクタのプロパティにデフォルト値を設定します。
            ALevelStreamerActor();
    
            // Called every frame
            virtual void Tick( float DeltaSeconds ) override;
    
        protected:
    
            // Called when the game starts or when spawned
            virtual void BeginPlay() override;
    
            UFUNCTION()
            void OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult);
    
            UPROPERTY(EditAnywhere)
            FName LevelToLoad;
    
        private:
            // Overlap volume to trigger level streaming
            UPROPERTY(VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
            UBoxComponent* OverlapVolume;
    
        };

    LevelStreamerActor.cpp は最終的にこのようになります。

        #include "Levels.h"
        #include "Kismet/GameplayStatics.h"
        #include "LevelStreamerActor.h"
    
        // Sets default values
        ALevelStreamerActor::ALevelStreamerActor()
        {
            // 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;
    
            OverlapVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("OverlapVolume"));
            RootComponent = OverlapVolume;
    
            OverlapVolume->OnComponentBeginOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapBegins);
        }
        // Called when the game starts or when spawned
        void ALevelStreamerActor::BeginPlay()
        {
            Super::BeginPlay();
    
        }
    
        // Called every frame
        void ALevelStreamerActor::Tick( float DeltaTime )
        {
            Super::Tick( DeltaTime );
    
        }
    
        void ALevelStreamerActor::OverlapBegins(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
        {
                ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
                if (OtherActor == MyCharacter && LevelToLoad != "")
                {
                    FLatentActionInfo LatentInfo;
                    UGameplayStatics::LoadStreamLevel(this, LevelToLoad, true, true, LatentInfo);
                }
        }
  9. コードをコンパイルしたら、エディタに切り替えます。

  10. LevelStreamer ブループリントをレベル内に配置して、Character にストリームを開始させたいパーシスタント ワールドの部分、 およびストリーミング レベルとなる歩行可能なボリューム全体を囲むように配置とスケールを調節します。

  11. Level to Stream として 「SunTemple_Streaming」 と入力します。

  12. ストリーミング レベルをテストするには、Play In Editor を使います。

C++ を使ってアンロードする

Character が BoxComponent からでる時にレベルをアンロードするには、UGameplayStatics::UnloadStreamLevel を呼び出して OnComponentEndOverlap へ結合する OverlapEnds 関数を作成します。次のコード スニペットを LevelStreamerActor: に追加します。

LevelStreamerActor.h への追加:

    UFUNCTION()
    void OverlapEnds(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

LevelStreamerActor.cpp への追加:

    void ALevelStreamerActor::OverlapEnds(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
    {
            ACharacter* MyCharacter = UGameplayStatics::GetPlayerCharacter(this, 0);
            if (OtherActor == MyCharacter && LevelToLoad != "")
            {
                FLatentActionInfo LatentInfo;
                UGameplayStatics::UnloadStreamLevel(this, LevelToLoad, LatentInfo);
            }
    }

コンストラクタへの追加:

    OverlapVolume->OnComponentEndOverlap.AddUniqueDynamic(this, &ALevelStreamerActor::OverlapEnds);
Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル