// Fill out your copyright notice in the Description page of Project Settings.
#include "WorldTester.h"
#include "MyWorldSubsystem.h"
// important
void AWorldTester::BeginPlay()
{
Super::BeginPlay();
UMyWorldSubsystem * ws = GetWorld()->GetSubsystem<UMyWorldSubsystem>();
ws->CallFunc();
}
Thanks for the detailed response. Let’s add a little more depth now…
There is no “BeginPlay” for my actor per say. The actor in question is a sub-class of AFunctionalTest as this is a functional unit test. StartTest is the function you override and put your test logic inside of. That’s where I’m retrieving the subsystem and calling its member function.
I then have an instance of UMyFunctionalTest dropped into an empty map (with FTEST_ as the prefix) and the automatio system picks it up. I launch the test from the session/automation frontend
I would point out that the functional test has no problem getting the world in order to retrieve the subsystem. It doesn’t make sense that the subsystem would then get a nullptr from GetWorld().
Question: how are you triggering StartTest? It’s not firing by default if I inherit from AFunctionalTest
Tick is enabled and it looks like it should execute but I’m not getting anything on my end.
Ok just noticed the session/automation part. I’ll look into it.
You can get the world context and world from the viewport
just added an int32 key in header to keep track of separate messages.
void AWorldTester::StartTest()
{
Super::StartTest();
FWorldContext* WorldContext = GEngine->GetWorldContextFromGameViewport(GEngine->GameViewport);
if (WorldContext)
{;
if (UWorld* World = WorldContext->World())
{
GEngine->AddOnScreenDebugMessage(key,2, FColor::Green,TEXT("World ok") + FString::FromInt(key));
key++;
UMyWorldSubsystem * WS = World->GetSubsystem<UMyWorldSubsystem>();
if (WS)
{
GEngine->AddOnScreenDebugMessage(key,2, FColor::Green,TEXT("World subsystem is ok") + FString::FromInt(key));
key++;
WS->CallFunc();
}
}
}
}
Apologies for the late response and thanks again for the effort. Let’s clear one thing up and mark this done.
So I don’t have an issue with GetWorld() under the StartTest function. This works just fine…
void UMyFunctionalTest::StartTest() {
Super::StartTest();
if(GetWorld()) { // This works just fine
UMySubsystem* MySubsystem = GetWorld()->GetSubsystem<UMySubsystem>();
if(MySubsystem) {
MySubsystem->Callfunc(); // The issue is in here
}
}
}
The issue is with the CallFunc method. A call to GetWorld() in there is what fails for me.
void UMySubsystem::CallFunc() {
if(GetWorld()) { // This fails for me
...
}
}
It’s as if the subsystem does not have an “Outer” from which to get the world from. I only see this during the functional test. Is this not what you’re seeing with yours?
It’s also possible that your calls to add the screen debug message is allowing some frames to pass such that everything is “caught up”. I’m only printing to a log file when GetWorld() fails. Maybe I’m just hitting an odd race condition.
Please elaborate on what type of class UMyFunctionalTest is. Seeming you mention dropping it into the world is it inherited from a UActorComponent inside of an actor? Mine is directly an actor.
Both should have UWorld accessible either way.
The class to extend is AFunctionalTest so it’s based on an actor class not a component class or uobject based. (it’s spawnable in the world). There is no U prefix, hence my confusion about what you are trying to achieve.
The only way where you would have a problem is if it was a UBlueprintFunctionLibrary. You can’t place them in the world though and would need to pass world context objects in the functions called inside of it.