修改的原因
- 我們目前的版本里面 大量來自協(xié)議的Dispatcher嚴重影響代碼的閱讀和維護
- 事件的邏輯處理和數(shù)據(jù)處理在框架層并沒有明確分開
- 事件派發(fā)能夠有效的減少直接引用
實現(xiàn)原理
在MobileZGameInstance中包含兩個代理函數(shù):OnProtocolRecvDelegate和PostProtocolRecvDelegate。當(dāng)網(wǎng)絡(luò)協(xié)議完成從protocol buffer轉(zhuǎn)化為ProtocolTemplate之后會連續(xù)執(zhí)行:
OnProtocolReceivedDelegate().Broadcast(ProtocolObject); PostProtocolRecvDelegate().Broadcast(ProtocolObject); ProtocolObject->Process(Ins)我們在c++代碼中完成他們的自動注冊。manager被默認為是在創(chuàng)建的時候自動注冊O(shè)nProtocolRecvDelegate,manager銷毀的時候清理代理, 所以可以認為Manager的注冊是永久的,UI則默認只注冊PostProtocolRecvDelegate,而且UI這邊是在Construct的時候進行自動注冊,Destruct的時候默認取消注冊,可以認為UI只會在顯示的時候處理協(xié)議。GameInstance Destroy的時候取消所有的注冊,
*當(dāng)上述兩個代理出發(fā)之后會執(zhí)行下面的Lambda函數(shù)
auto ProcessLambda = [=](UObject* Protocol, const TCHAR* Prefixes)
{
FString ClassName, RightName;
Protocol->GetClass()->GetName().Split(TEXT("_C"), &ClassName, &RightName);
FName FunctionName = FName(*(FString::Printf(TEXT("%s%s"), Prefixes, *ClassName)));
UFunction* Function = Excuter->FindFunction(FunctionName);
if (Function)
{
void* Parameters = (void*)(&Protocol);
Excuter->ProcessEvent(Function, Parameters);
}
};
OnProtocolReceivedDelegate代理的Prefixes 是OnRecv,PostProtocolRecvDelegate的Prefixes 是PostRecv
所以如果一個注冊了兩個代理的對象類中如果含有Prefixes +協(xié)議名函數(shù)名的函數(shù),那么該函數(shù)將會執(zhí)行。相當(dāng)于對協(xié)議的抵達做了相應(yīng)的處理。
函數(shù)名字舉例:OnRecvActivationKeyRsp, PostRecvActivationKeyRsp
用法
- 如果一個類希望能夠綁定上述的兩個代理,需要實現(xiàn)接口類IProtocolProcessInterface
- 需要在適當(dāng)?shù)牡胤秸{(diào)用
RegisterDelegate和UnRegisterDelegate - 按照需要實現(xiàn)自己的方法OnRecv+Protocol,既可以在c++中也可以在BP中實現(xiàn)該函數(shù),c++中使用UFUNCTION標(biāo)記函數(shù),BP中直接聲明函數(shù)即可。
uml圖: https://www.processon.com/view/link/584627dee4b0e742e4a9dcdd