very good content
are you already working on this paper?
Thank you, this encouraged me to add some more content to this:
https://github.com/SyedAman/UnrealEngineDeepDive/commit/2d3da4d30245e98f8499a316d41781398055a22e
I am working on my own game engine currently and have not been able to fill this out as much, but I will try to add to this. Is there any part you are particularly interested in?
I'm interests in unreal engine architecture and more detail exploration how it works on real examples. I know a little bit about standalone classes such as game-play, state, pawn, etc.. but I need to get more information about plugin development. For example, I develop someapp and I not sure that code share its a good idea for my project. So I need know how I can write API for my plugin developers which can access to my main features in my app via that API in the runtime.
Running ue5App::API_Interface <=> Custom_Plugin (without direct accessing to ue5App src code, only via API methods based on mainApp signatures)
P.S. I'm not pro in C++, but I thinking it would be working.
For example this is custom plugin with event handler (where msgId arrowed to the signature from main call stack):
register_event(EventMsgId_or_SomethingElse:"ue5_Main_App_Event_client_connected", f():callbackF, Boolean:post_or_pre_hook_method)
// .. other stuff
public TheCustomPlugin::callbackF(const int msgId, ... other_params ) {
// Do plugin logics based on msg signature
// Like msg with 98 id structure:
// 1 param - userid
// 2 param - hash
// and much more..
//
// And return code (0 - continue base event without changes, 1 - handled but return 0 for base event, 2 - override event main params in source call stack)
}
p.s.s. looks like I need to share memory pointers to some main app structures )))
Here are two solutions.
In your ue5 app:
// IAPI_Interface.h
#pragma once
#include "IAPI_Interface.generated.h"
UINTERFACE(MinimalAPI)
class UAPI_Interface : public UInterface
{
GENERATED_BODY()
}
class IAPI_Interface
{
GENERATED_BODY()
public:
void RegisterClientConnectedEvent(const FName& EventName, const FDelegateHandle& DelegateHandle);
void TriggerClientConnectedEvent(const FName& EventName, int32 ClientId, const FString& ClientInfo);
};
//MyAPIManager.h
#pragma once
#include "CoreMinimal.h"
#include "IAPI_Interface.h"
#include "MyAPIManager.generated.h"
UCLASS()
class UMyAPIManager : public UObject, public IAPI_Interface
{
GENERATED_BODY()
public:
TMap<FName, FClientConnectedDelegate> ClientConnectedEventMap;
void RegisterClientConnectedEvent(const FName& EventName, const FDelegateHandle& DelegateHandle);
void TriggerClientConnectedEvent(const FName& EventName, int32 ClientId, const FString& ClientInfo);
};
//MyAPIManager.cpp
#include "MyAPIManager.h"
void UMyAPIManager::RegisterClientConnectedEvent(const FName& EventName, const FDelegateHandle& DelegateHandle)
{
if (!ClientConnectedEventMap.Contains(EventName)) {
ClientConnectedEventMap.Add(EventName, FClientConnectedDelegate());
}
ClientConnectedEventMap[EventName].Add(DelegateHandle);
}
void UMyAPIManager::TriggerClientConnectedEvent(const FName& EventName, int32 ClientId, const FString& ClientInfo)
{
if (ClientConnectedEventMap.Contains(EventName)) {
ClientConnectedEventMap[EventName].Broadcast(ClientId, ClientInfo);
}
}
PLUGIN
#include "PluginModule.h"
#include "Interfaces/IAPI_Interface.h"
void FPluginModule::StartupModule()
{
// Locate the API interface in the main application
UMyAPIManager* APIManager = FindObject<UMyAPIManager>(ANY_PACKAGE, TEXT("MyAPIManager"), true);
if (APIManager) {
// Register to listen for the 'ClientConnected' event
FClientConnectedDelegate::FDelegate ClientConnectedDelegate = FClientConnectedDelegate::FDelegate::CreateRaw(this, &FPluginModule::HandleClientConnected);
FDelegateHandle DelegateHandle = APIManager->ClientConnectedEventMap.Add(FName("ClientConnected"), ClientConnectedDelegate);
}
}
void FPluginModule::ShutdownModule()
{
// Unregistering events, if necessary, would go here
}
void FPluginModule::HandleClientConnected(int32 ClientId, const FString& ClientInfo)
{
UE_LOG(LogTemp, Log, TEXT("Client %d connected with info: %s"), ClientId, *ClientInfo);
}
Alternative solution that uses less Unreal Engine - specific syntax
// UE5App_API_Interface.h
#pragma once
#include "CoreMinimal.h"
#include "Modules/ModuleManager.h"
class IUE5AppAPIInterface
{
public:
virtual ~IUE5AppAPIInterface() = default;
virtual void RegisterEvent(FString EventName, std::function<void(int, TArray<FString>)> Callback, bool bPostEvent) = 0;
virtual void UnregisterEvent(FString EventName) = 0;
};
// Expose the interface to other modules
extern "C" UE5APP_API IUE5AppAPIInterface* GetUE5AppAPI();
// UE5App_API_Interface.cpp (Implementation in main app)
#include "UE5App_API_Interface.h"
class FUE5AppAPI : public IUE5AppAPIInterface
{
public:
virtual void RegisterEvent(FString EventName, std::function<void(int, TArray<FString>)> Callback, bool bPostEvent) override
{
// Implementation to register the event and callback in the main app
}
virtual void UnregisterEvent(FString EventName) override
{
// unregister the event
}
};
// Global instance
static FUE5AppAPI UE5AppAPIInstance;
// Exported function
extern "C" UE5APP_API IUE5AppAPIInterface* GetUE5AppAPI()
{
return &UE5AppAPIInstance;
}
// CustomPlugin.cpp (Usage in custom plugin)
#include "UE5App_API_Interface.h"
class FCustomPlugin
{
public:
FCustomPlugin()
{
// Get the API interface from the main app
IUE5AppAPIInterface* API = GetUE5AppAPI();
if(API)
{
API->RegisterEvent(TEXT("ue5_Main_App_Event_client_connected"),
[this](int MsgId, TArray<FString> Params)
{
this->EventHandler(MsgId, Params);
},
false);
}
}
~FCustomPlugin()
{
IUE5AppAPIInterface* API = GetUE5AppAPI();
if(API)
{
API->UnregisterEvent(TEXT("ue5_Main_App_Event_client_connected"));
}
}
void EventHandler(int MsgId, TArray<FString> Params)
{
// Handle the event, e.g. log message or manipulate parameters
if(MsgId == 98)
{
// Custom logic for message with ID 98
}
}
};
// Declare a global instance of the plugin to ensure its constructor is called
static FCustomPlugin CustomPluginInstance;
If this makes sense for you, I might add it to the paper as example code for using Plugins
Did that work for you? @KGB1st
Hi , Appreciate your work ☺️☺️. It's a request to add some more information about unreal engine architecture, some of the information you have not added.