Game flow programming - loading/unloading levels, spawning actors/componeents, etc

I’ve been digging around a bit this morning and I can’t really seem to find any good documentation on lower level game flow in UE4 using C++ rather than Blueprint. Pretty much everything seems to assume you are using Blueprint for your game flow/game logic.

And that is all well and good except I am writing unit tests so BP isn’t an option.

Is there some documentation or tutorial out there that I just am missing that covers doing things from C++ like loading and unloading of levels, spawning actors, destroying actors, adding and destroying components to actors, etc? Some google searches bring up hits for UGameplayStatics which seems to have zero actual documentation in the Wiki. Same with GEngine. A lot of code seems to use it but I can’t find any documentation on it.

Any help would be appreciated. Right now I am really struggling just to get some basic unit tests up and running such as something like:
Load level
Spawn Actor of Type X
Add component of Type Y to Actor
Test some code
Destroy Actor and Component
Unload level

I’m learning this too so take my suggestions with a grain of salt. I can say though I experienced what you are going through firsthand. Some things of interest are:

Blueprints and C++ work hand-in-hand. That is, I’ll create a C++ class based of UGameInstance, AGameMode, UUserWidget, AActor, APawn, APlayerController, and others with the intent of exposing class members to the Blueprint Graph Editor via BlueprintType, BlueprintReadWrite, BlueprintCallable, BlueprintImplementableEvent, etc.

Start with a class that inherits from UGameInstance since the class will exist for the life of your program. Put things that you would like to be accessible from other parts of your game. One item in particular is an FStreamableManager that is used for loading assets, both synchronously and asynchronously. You can access your game instance via:



UMyGameInstance* gameInstance = Cast<UMyGameInstance>(GetWorld()->GetGameInstance())


Next add a class that inherits from AGameMode that will be your starting game mode. My starting game mode is for my menu (set in the UE4 Editor: Settings → Project Settings → Maps & Modes → Default GameMode . . . and your map). Then use UUserWidget (or other) for your various menu’s. For me I have a base class that inherits from UUserWidget, and then items such as Main Menu, and child menus inherit from it. More importantly the UUserWidget menus are built in the Graph Editor, tied to members of my class, and assigned to my game mode with TSubclassOf.

Display of the UUserWidget’s can be done with the following:



UUserWidget* UMyGameInstance::CreateMenu(TSubclassOf<UUserWidget> Menu)
{
    UUserWidget* NewMenu = CreateWidget<UUserWidget>(GetWorld(), Menu);

    return NewMenu;
}


void UMyGameInstance::ShowMenu(UUserWidget* Menu)
{
    if (Menu != nullptr)
    {
        Menu->AddToViewport();
    }
}


void UMyGameInstance::HideMenu(UUserWidget* Menu)
{
    if (Menu != nullptr)
    {
        Menu->RemoveFromViewport();
    }
}


Once you get your Menu composed in the Blueprint Graph Editor, and you have a Button control that calls a function in your class, for example, loading a selected level, then you can perform something similar to the below depending if you want perform a full load or stream:



void UMyGameInstance::FullLoad(FName levelPath)
{
    UGameplayStatics::OpenLevel(this, levelPath, false);
}


void UMyGameInstance::Streaming(FName levelPath)
{
    ULevelStreaming* pStreaming = UGameplayStatics::GetStreamingLevel(GetWorld(), levelPath);

    if (pStreaming)
    {
        pStreaming->bShouldBeLoaded = true;
        pStreaming->bShouldBeVisible = true;
    }
}


In some situations you may want to have a manager for a particular type of actor control the spawning of them. In that case you can derive from AActor, and during the Tick event spawn the object when needed:



.h
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Spawn My Actor")
    TArray<TAssetSubclassOf<AMyPawn>> MyDifferentPawns;


.cpp

void AMyManager::BeginPlay()
{
    Super::BeginPlay();

    int32 pawnCount = MyDifferentPawns.Num();

    for (int32 x = 0; x < pawnCount; x++)
    {
        if (MyDifferentPawns[x].IsPending())
        {
            gameInstance->AssetLoader.SimpleAsyncLoad(MyDifferentPawns[x].ToStringReference());
        }
        else
        {
            AMyPawn* pawn = MyDifferentPawns[x].Get()->GetDefaultObject<AMyPawn>();
            pawn->ReInitializeHere();
        }
    }
}


void AMyManager::Tick(float DeltaSeconds)
{
    Super::Tick(DeltaSeconds);

    nextSpawnTime += DeltaSeconds;

    if (nextSpawnTime >= SpawnTimer)
    {
        SpawnActor();
        nextSpawnTime = 0.0f;
    }
}


bool AMyManager::SpawnActor()
{
    FVector spawnLocation = FVector(0.0f, 0.0f, 0.0f);
    FRotator spawnRotation = FRotator::ZeroRotator;

    int p = FMath::RandRange(0, MyDifferentPawns.Num() - 1);

    if (MyDifferentPawns[p].IsValid())
    {
        AMyPawn* pawn = GetWorld()->SpawnActor<AMyPawn>(MyDifferentPawns[p].Get(), spawnLocation, spawnRotation);
        :
        :
    }
}


This is just a basic guideline to consider/follow. . .and not sure if it’s kosher or not with the UE4 framework. But it does work for me with my limited requirements.

Here are some unfiltered notes that may help:



    Loading Levels
    -----------------------------------------------------------------------------------------------------------------------
    https://answers.unrealengine.com/questions/217404/how-to-dynamically-load-umaps-c.html

    Gameplay Guide                              https://docs.unrealengine.com/latest/INT/Gameplay/index.html
    Gameplay Framework                          https://docs.unrealengine.com/latest/INT/Gameplay/Framework/index.html
    Gameplay Framework Quick Reference          https://docs.unrealengine.com/latest/INT/Gameplay/Framework/QuickReference/index.html

    GameMode                                    https://docs.unrealengine.com/latest/INT/Gameplay/Framework/GameMode/index.html
    GameState                                   https://docs.unrealengine.com/latest/INT/Gameplay/Framework/GameState/index.html


    UGameEngine                                 https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UGameEngine/index.html
    UWorld                                      https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UWorld/index.html
    FWorldContext                               https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/FWorldContext/index.html

    UEngine::LoadMap                            https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UEngine/LoadMap/index.html
    FSeamlessTravelHandler                      https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/FSeamlessTravelHandler/index.html


    Level Loading and Management
    -----------------------------------------------------------------------------------------------------------------------
    https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/ULevel/index.html
    https://docs.unrealengine.com/latest/INT/GettingStarted/RunningUnrealEngine/index.html
    https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/Engine/UEngine/LoadMap/index.html


    Input Handling
    -----------------------------------------------------------------------------------------------------------------------
    https://answers.unrealengine.com/questions/161246/gamepad-controller-for-umg.html
    https://docs.unrealengine.com/latest/INT/API/Runtime/UMG/Blueprint/UUserWidget/index.html
    https://docs.unrealengine.com/latest/INT/API/Runtime/UMG/Blueprint/UUserWidget/OnKeyDown/index.html


    Referencing Assets
    -----------------------------------------------------------------------------------------------------------------------
    https://docs.unrealengine.com/latest/INT/Programming/Assets/ReferencingAssets/index.html
    https://docs.unrealengine.com/latest/INT/Programming/Assets/AsyncLoading/index.html
    https://forums.unrealengine.com/showthread.php?5309-TUTORIAL-C-Runtime-Async-Load-Modular-Character-(Intermediate


    Possible links to check on
    -----------------------------------------------------------------------------------------------------------------------
        https://docs.unrealengine.com/latest/INT/Engine/Blueprints/TechnicalGuide/ExtendingBlueprints/index.html
        https://docs.unrealengine.com/latest/INT/Gameplay/ClassCreation/CodeAndBlueprints/index.html
        https://docs.unrealengine.com/latest/INT/Gameplay/ClassCreation/BlueprintOnly/index.html
        https://docs.unrealengine.com/latest/INT/Gameplay/ClassCreation/index.html
        https://docs.unrealengine.com/latest/INT/Gameplay/ClassCreation/CodeOnly/index.html
        https://docs.unrealengine.com/latest/INT/Engine/Blueprints/TechnicalGuide/ExtendingBlueprints/index.html

        https://docs.unrealengine.com/latest/INT/API/Runtime/UMG/Components/UTextBlock/index.html
        https://docs.unrealengine.com/latest/INT/API/Runtime/UMG/Components/UEditableTextBox/index.html


Wow that is really an “Above and Beyond” post and I appreciate it! Some good nuggets in there fore sure.

This link may help you out too John :slight_smile:

Thanks but I had already seen that and was looking for more basic level stuff. Almost all of the UE docs seem to sit at a higher level and gloss over the base level stuff, which I really think is designed to be handled by Blueprint. And I’m fine with that in general, but like I said originally you can’t always use Blueprint even if you want to :slight_smile:

Good info , I too and just diving into the C++ stuff, and am trying to straighten out the whole gameinstance vs gamemode vs gamestate stuff. I thought I had read that gamemode is only available on the server ( i am planning a multiuser game), that the clients don’t have access as it contains all the stuff that you do not want anyone to be able to ‘hack’.

I was curious if you actually start with gameinstance and use that for saving all the stuff you need to save/load… do the menu stuff… and gamemodes were more like ‘deathmatch’ ‘searchanddestroy’ etc. Or perahps a base gamemode that has stuff that is common to all modes that may be played (or planned) and those are just children of that gamemode. If any of that makes sense.