I’m developing a Game in Unreal 5.1 which uses a geolocation service to get the latitude and longitude of the player’s computer.
Here it’s the header file:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Online/HTTP/Public/Http.h"
#include "PlayerGeoLocationActor.generated.h"
// Delegate signature
DECLARE_DYNAMIC_DELEGATE_TwoParams(FOnGetGeoLocationSignature, double, Latitude, double, Longitude);
UCLASS()
class PLANETARIUMSTARSTEST_API APlayerGeoLocationActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
APlayerGeoLocationActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
FOnGetGeoLocationSignature OnGetGeoLocationDelegate;
private:
void SendGetHttpRequest(const FString& Url);
/*Called when the server has responded to our http request*/
void OnResponseReceived(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful);
};
And the code file:
#include "PlayerGeoLocationActor.h"
#include "Serialization/JsonSerializer.h"
// Sets default values
APlayerGeoLocationActor::APlayerGeoLocationActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void APlayerGeoLocationActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void APlayerGeoLocationActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void APlayerGeoLocationActor::SendGetHttpRequest(const FString& Url)
{
// Create Request.
TSharedRef<IHttpRequest> Request = FHttpModule::Get().CreateRequest();
// Binding a function that will fire when we receive a response from our
// request.
Request->OnProcessRequestComplete().BindUObject(
this,
&APlayerGeoLocationActor::OnResponseReceived);
// This is the url on which to process the request
Request->SetURL(Url);
// We're getting data so set the Http method to GET.
Request->SetVerb("GET");
Request->SetHeader("User-Agent", "X-UnrealEngine-Agent");
Request->SetHeader("Content-Type", "application/json");
Request->ProcessRequest();
}
void APlayerGeoLocationActor::OnResponseReceived(
FHttpRequestPtr Request,
FHttpResponsePtr Response,
bool bWasSuccessful)
{
if (bWasSuccessful)
{
// Single json value (any of supported json types e.g.
// object with properties, array, bool) at top level of json.
TSharedPtr<FJsonValue> JsonValue;
FString JsonResponse = Response->GetContentAsString();
// Create a reader pointer to read the json data
TSharedRef<TJsonReader<>> Reader =
TJsonReaderFactory<>::Create(JsonResponse);
// Deserialize the json data given Reader and the actual object to
// deserialize.
if (FJsonSerializer::Deserialize(Reader, JsonValue)) {
// Get the value of the json object by field name
double Latitude = JsonValue->AsObject()->GetNumberField("latitude");
double Longitude = JsonValue->AsObject()->GetNumberField("longitude");
OnGetGeoLocationDelegate.ExecuteIfBound(Latitude, Longitude);
}
}
}
The above code is a class that manages get the player’s location.
I have a design question: I don’t know what to do when I deserialize the latitude
and logitude
.
I’ve though to use a delegate and called after I get the two values.
Is it a good design to do it this way? I’m calling OnGetGeoLocationDelegate.ExecuteIfBound(Latitude, Longitude);
within APlayerGeoLocationActor::OnResponseReceived
.
I am in doubt because I’m going to call a delegate within a delegate. Or maybe I’m not doing that and I haven’t understood anything.
Thanks.