4

I have an Editor Widget and inside of it I created a blueprint for some button click event.

Unfortunately, when I use the "Get game state" node (or any similar), it always returns null.

I understand that it's correct while I don't hit Play in Editor (there's no game state instance). But once I do hit Play, it's all the same when I click the button on Editor Widget - it returns null. At the same time, regular widgets inside game window do return the game state reference.

So, making assumption that the game is playing (I hit Play button), how to get access to Game State inside Editor Widget (like it's possible in normal Widget)?

p.s. I am working on simple, single-player case.

PolGraphic
  • 3,233
  • 11
  • 51
  • 108

1 Answers1

5

You must have a valid World Context Object.

When Get Game State node is used inside an Editor Utility Widget, the World Context Object pin is exposed.

Get Game State node in a Widget Blueprint

In Actor Blueprints, the World Context Object is still there, but the editor hides the pin because it can be automatically determined.

Get Game State node in an Actor Blueprint

A World Context Object is any UObject that can get back to a UWorld object. In the case of the Actor Blueprint, the blueprint editor can simply use that actor as the World Context Object, by passing that actor to GetWorldFromContextObject.

Your Editor Widget Blueprint, on the other hand, does not have an object tied to an object that can be used as a World Context Object, so you must provide one somehow.

Using the Selected Actor from Blueprints

Here is an example of how to get the Game State using the selected actor as the World Context Object. To use this example, create an Editor Utility Blueprint with a single button and use the Blueprint graph below as the button click handler. Then run the widget, and start Play in Editor, then disposess the player (F8), select any actor in the scene, and click the button. You should see the current time logged.

Using Get Game State in an Editor Utility Widget Blueprint

Using C++

Alternatively, you can create a Blueprint callable C++ function that directly loops through the engine's worlds and returns the most appropriate one to Blueprints.

The .h file

UCLASS()
class MYPROJECT_API AMyProjectGameModeBase : public AGameModeBase
{
    GENERATED_BODY()

public:

    UFUNCTION(BlueprintCallable)
    static UWorld* MyGetWorld();

};

The .cpp file

#include "Engine/Engine.h"

UWorld* AMyProjectGameModeBase::MyGetWorld()
{
    // Prefer PIE Worlds.
    // Fallback to Game Preview Worlds.
    // Ignore all other types (e.g., other preview worlds).

    UWorld* PIE = nullptr;
    UWorld* GamePreview = nullptr;

    for (FWorldContext const& Context : GEngine->GetWorldContexts())
    {
        switch (Context.WorldType)
        {
        case EWorldType::PIE:
            PIE = Context.World();
            break;
        case EWorldType::GamePreview:
            GamePreview = Context.World();
            break;
        }
    }

    if (PIE)
    {
        return PIE;
    }
    else if (GamePreview)
    {
        return GamePreview;
    }

    return nullptr;
}

Note that for this example I put the function in the game mode, which is probably not where you'd put it organizationally, but it's just for demonstration since the game mode C++ file is automatically created when you make a new C++ project from the Basic template.

Also note that what you are trying to do is kind of sketchy. An Editor Utility is meant to run in the context of the editor, which can survive the loading of many worlds. If you want to be able to press a button that interacts with the scene, you might be better off doing one of the following instead:

  • Put a debug button in the game itself using UMG or Slate
  • Create a console command in the game itself (may require C++, I've never tried this in blueprints)
  • If this is only meant to work with a specific type of actor, create a custom details panel for that actor (requires C++).
Doug Richardson
  • 10,483
  • 6
  • 51
  • 77