Download

How to get UWorld* from a background thread

Hi,

I’m developing a TCP client to connect to a 3th party server. I’m using the networking classes from UE4 (FSocket) and for receiving the packets from the server I’m running a background thread initialized by a non-game class (I mean, the class doesnt inherit from UObject).

When a packet arrives I need to get a reference to the actual UWorld in order to get the actual playing level, set animations, spawn actors, etc.

As far as I could find here in the forums, the suited method for that would be GEngine::GetWorld(). GEngine should be a static class that lives from the start of the first level to the end of the game and its GetWorld method should return the actual playing UWorld. Could anyone confirm that?

Also, when calling


GEngine->GetWorld()

from that recv thread I always get a nullptr. Does anyone have any idea why is that happening?

I posted this question in the question hub but only got 1 view aside from mines (3 total). I’m trying to reply the question here hoping that the community is more active here. UE4 have such a steep learning curve, with a poor documentation for deep programming, if the community is really that scarce I guess it’s not worth to stick with the engine to make my project. Even with a strong c++ background I got stuck every now and then due to poor documentation, it’s frustrating to see that the docs are just the code-comments as a html page. (link to the other post here: https://answers.unrealengine.com/questions/602420/how-to-get-uworld-from-a-background-thread.html ).

GetWorld() won’t return anything unless you call from an Actor or UObject instatiated inside of one of the multiple UWorlds in runtime.
Calling GetWorld() from static GEngine will always give you a nullptr because there’s no World (Level Map) there;
You need an Actor as an interface to the World between the Game and your external static code to know which UWorld it is in.

So the solution for this would be put the networking code in an Actor instantiated in the first level and keep it alive from level changes?

Thanks for the reply.

You can’t safely do these things from any thread other than the game thread anyway. You need to have your network controller pass notifications of the received events to something on the game thread - probably by using a queue along with either a synchronization object, or just checking the queue from your game thread object on tick.

I think going down a separate thread route is not necessary. I connect to Azure this way… You can see there is a callback being set up…


	FGuid guid = FGuid::NewGuid();
	TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
	FString url = FString::Printf(TEXT("https://%s.table.core.windows.net/%s"), *_application, *resource);
	HttpRequest->SetURL(url);
	HttpRequest->SetVerb(TEXT("GET"));
	FString date = GeometryHelper::GetAzureDate();
	HttpRequest->SetHeader(TEXT("x-ms-date"), date);
	FString auth_sig = GenerateSignature(date, _application, resource);
	FString auth = FString::Printf(TEXT("SharedKeyLite %s:%s"), *_application, *auth_sig);
	HttpRequest->SetHeader(TEXT("Authorization"), auth);
	HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json"));
	HttpRequest->SetHeader(TEXT("Accept-Charset"), TEXT("UTF-8"));
	HttpRequest->SetHeader(TEXT("x-ms-client-request-id"), guid.ToString(EGuidFormats::DigitsWithHyphens));
	HttpRequest->SetHeader(TEXT("Accept"), TEXT("application/json;odata=nometadata"));
	HttpRequest->SetHeader(TEXT("x-ms-version"), TEXT("2015-04-05"));
	HttpRequest->OnProcessRequestComplete().BindUObject(this, &UJsonHelper::OnProcessRequestComplete);
	// Execute the request
	HttpRequest->ProcessRequest();