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

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

Windows
MacOS
Linux

レベル ストリーミングのシナリオ

Sun Temple プロジェクトのメイン レベルから始めます。レベルを室内空間と、海が見える柱つきの中庭に分割します。 以下のワイヤーフレーム ビューでは、ティール色のワイヤーフレームがパーシスタント室内レベルを示し、黄色のワイヤーフレームがストリーミングされる中庭レベルを示します。 空と屋外が見えるように寺院の主要部にはいくつか窓があるので、空と海はパーシスタント レベルです。

LevelSplit.png

寺院の内装には、中庭を視界から隠す廊下を混ぜます。

StartLoading.png

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

StreamingLevelVisible.png

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

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

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

    PlayerStart.png

  3. ウィンドウ 上をクリックして、レベル を選択します。

    WindowLevels.png

  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:
    // Overlap volume to trigger level streaming
    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 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:
        // Sets default values for this actor's properties (このアクタのプロパティのデフォルト値を設定します)
        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. (フレーム毎に Tick() を呼び出すようにこのアクタを設定) 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 関数を作成します。次のコード スニペットを
your 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);
Select Skin
Light
Dark

Welcome to the new Unreal Engine 4 Documentation site!

We're working on lots of new features including a feedback system so you can tell us how we are doing. It's not quite ready for use in the wild yet, so head over to the Documentation Feedback forum to tell us about this page or call out any issues you are encountering in the meantime.

We'll be sure to let you know when the new system is up and running.

Post Feedback