// 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 AMyFunctionalTest 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 AMyFunctionalTest::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.
@3dRaven I’m back! Apologies, I fell off the map there for a bit
Just a typo. I didn’t want to add noise with surrounding code so instead of copy/paste I just wrote code on the fly mimicking what I was doing in the actual code. I’ve gone back and edited my comments to reflect that. Your setup is in fact the same as mine, an actor sub-classed from AFunctionalTest so all good there.
That said, it still doesn’t work and neither does your code when I pull it into my project…and that’s where the issue is, my project. I tested the setup using my code and your code on a clean project and everything worked as expected. Through some debugging I found that I was blowing the stack elsewhere, ultimately corrupting my session.
I should have tested on a clean project before posting to begin with. Apologies for the time waste . I’ve gone ahead and marked your solution as it is a good representation of a base setup and I appreciate the time you took and effort put in.