是什么
代理的意思:代替/代表他人处理某些事情
为什么
想到一个应用场景: 当角色升级时,需要改变UI等级提示,需要播放特效等等。如果不使用代理,代码大概是下面这个样子,角色代码里需要存放各种各样的指针,逻辑高度耦合。
class UI{
};
class Effective{
};
class MyCharactor{
public:
....
void LevelUp(){
ui->ChangeLevel();
eff->PlayLevel();
}
private:
UI* ui;
Effective* eff;
};
使用代理后,大概是这样子,角色解耦(观察者模式)
class MyCharactor{
public:
....
DECLARE_MULTICAST_DELEGATE(FLevelUpDelegate);
void LevelUp(){
LevelUpDelegate.brocast();
}
FLevelUpDelegate LevelUpDelegate;
};
class UI{
public:
MyCharactor *MyChar = GetCharactor();
MyChar->LevelUpDelegate.Add(this, &ChangeLevel);
}
怎么做
单播
例子:
DECLARE_DELEGATE_OneParam(PintIntDelegate, int);//声明代理类型
class IntContainer{
public:
IntContainer(int inval)
: val(inval)
{
}
void PrintFunc(int a){
UE_LOG(TempLog, Log, TEXT("IntContainer::PrintFunc: %d"), val+a);
}
private:
int val;
}
int main(){
IntContainer IntCont(10);
PintIntDelegate printDel; //实例化代理
printDel.Bind(&IntCont, &IntContainer::PrintFunc);//绑定代理函数
printDel.Execute(23);//执行代理函数. 输出33
}
代理类型:
绑定类型:
执行类型:
多播
例子:
DECLARE_MULTICAST_DELEGATE(MultiDelegate);//声明代理类型
class IntContainer{
public:
IntContainer() = default;
void PrintFunc1(){
UE_LOG(TempLog, Log, TEXT("IntContainer::PrintFunc1));
}
void PrintFunc2(){
UE_LOG(TempLog, Log, TEXT("IntContainer::PrintFunc2));
}
private:
int val;
}
int main(){
IntContainer IntCont();
MultiDelegate multiDelegate; //实例化代理
multiDelegate.AddRaw(&IntCont, &IntContainer::PrintFunc1);//绑定代理函数
multiDelegate.AddRaw(&IntCont, &IntContainer::PrintFunc2);//绑定代理函数
multiDelegate.Broadcast;//执行代理函数. 输出
}
代理类型:
绑定类型:
执行类型:
注意: 多播没有返回值
动态播
动态播支持序列化,可供蓝图使用,但是效率比较低。
声明时需要F开头,蓝图需要用 UPROPERTY(BlueprintAssinable) 修饰;
声明到蓝图绑定事件:
DEClARE_DYNAMIC_MULTICAST_DELEGATE(FDynamicMultiDelegate);
UClass()
class xxx: public AActor
{
...
UPROPERTY(BlueprintAssinable)
FDynamicMultiDelegate DynamicMultiDelegate
}
例子:
..
声明类型:
代理类型:
执行类型:
事件代理
声明类型:
OwningType为事件的友元类,可以调用事件的私有函数,如Broadcast();
代理类型(与多播一样):
执行类型:
参考: