从仿函数到std::function再到虚幻4 Delegate

这几天研究了一下虚幻4的delegate,但是想要理解这个,还得从仿函数说起。仿函数的定义是:A Functor is a object which acts like a function. Basically, a class which defines operator().下面是一段代码例子:

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

The real advantage is that a functor can hold state.(这就是仿函数的最大好处)

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}

不过上面这种玩法是很久以前的了,现在还可以使用std::function(例子二:)-----------------------------------------------

#include 
#include 
#include 
using namespace std;

class MyCharacter
{
public:
	void BeHurt01(int hurtvalue)
	{
		cout << "hurt01" << hurtvalue << endl;
	}

	void BeHurt02(int hurtvalue)
	{
		cout << "hurt02" << hurtvalue << endl;
	}
};

class OtherCharacter
{
public:

	functionThisIsDelegate;

};

int main()
{
	MyCharacter mycha;
	OtherCharacter othecha;

	othecha.ThisIsDelegate = bind(&MyCharacter::BeHurt01, &mycha, placeholders::_1);

	othecha.ThisIsDelegate(19);



	return 0;
}


这样做的好处就是实现延迟调用,我先把方法绑上去,到我需要的时候再调用。这么说可能有点抽象。既然是做游戏的,可以举个例子来说明。比如我现在有个主角和一个怪物。主角打出去一拳后会对怪物造成伤害,但是这个伤害不是立刻起效的,因为需要完成动画播放,主角的出招的特效播放之后才会执行怪物受伤扣血的逻辑。这时候可以先在主角出招的时候探测周围的怪物然后给他们绑定上伤害函数。等怪物的动画播放完毕之后再判断是否要执行这个伤害操作。这个时候就需要上面那种办法了。

相对于函数指针,std::function能绑定c++里的所有可调用对象,stdfunction相当于帮我们封装了一个模板。

再来说虚幻的delegate。虚幻的delegate其实就是更高级的封装了。

首先声明几个函数和代理,注意代理的格式和函数对应

头文件:
/*Single-cast delegate declaration. No parameters*/
DECLARE_DELEGATE(MyDelegate)
 
/*Single-cast delegate declaration. One int32 parameter*/
DECLARE_DELEGATE_OneParam(MyIntDelegate,int32)
 
/*Multi-cast delegate declartion. One int32 parameter*/
DECLARE_MULTICAST_DELEGATE_OneParam(MyIntMulticastDelegate,int32)
 
/*Function with one int32 parameter*/
UFUNCTION()
void IntFunction(int32 x);
 
/*Function with one int32 parameter*/
UFUNCTION()
void SecondIntFunction(int32 x);
 
/*Function with one int32 parameter*/
UFUNCTION()
void ThirdIntFunction(int32 x);
 
/*Function with no parameters*/
UFUNCTION()
void SomeFunction();
源文件:
void ADelegateActor::IntFunction(int32 x)
{
    GLog->Log("Output from IntFunction: " + FString::FromInt(x));
}
 
void ADelegateActor::SecondIntFunction(int32 x)
{
    GLog->Log("Output from SecondIntFunction: " + FString::FromInt(x*2));
}
 
void ADelegateActor::ThirdIntFunction(int32 x)
{
    //x to square
    float power = FMath::Pow(x, 2);
    GLog->Log("Third Int Function: "+FString::SanitizeFloat(power));
}
 
void ADelegateActor::SomeFunction()
{
    GLog->Log("Some function log");
}
在beginplay函数中做如下绑定:
//Declaring a delegate of MyDelegate type
MyDelegate MyDel;
//Binding a UFUNCTION to MyDel - this will not call the function just yet.
MyDel.BindUFunction(this, FName("SomeFunction"));
 
//Calling the bound function of the delegate
MyDel.Execute();
 
//Declaring a delegate of MyIntDelegate type
MyIntDelegate IntDelegate;
 
//Binding two UFUNCTIONs to IntDelegate - this will not call any function just yet
IntDelegate.BindUFunction(this, FName("IntFunction"));
IntDelegate.BindUFunction(this, FName("SecondIntFunction"));
 
//Since the IntDelegate is a single-cast delegate it will only contain up to one function
//In this case, the IntDelegate contains the last bound function
IntDelegate.Execute(50);
 
//Declaring a delegate of MyIntMulticastDelegate type
MyIntMulticastDelegate Del;
 
//Adding three UFUNCTIONs to the delegate - this will not call any function just yet
Del.AddUFunction(this, FName("IntFunction"));
Del.AddUFunction(this, FName("SecondIntFunction"));
Del.AddUFunction(this, FName("ThirdIntFunction"));
 
//Calling all the bound functions with a value of 10
Del.Broadcast(10);

上面的代码中详细罗列了UFunction函数绑定代理的各个方法,下面来搞一个例子吧:

首先我们建立一个第三人称c++模板工程

从仿函数到std::function再到虚幻4 Delegate_第1张图片

然后打开代码,在MyProjectCharacter.h中声明一个代理,两个与之匹配的函数

从仿函数到std::function再到虚幻4 Delegate_第2张图片

在构造函数中将函数和代理绑定

从仿函数到std::function再到虚幻4 Delegate_第3张图片

从仿函数到std::function再到虚幻4 Delegate_第4张图片

在MoveForward函数里执行这个代理
从仿函数到std::function再到虚幻4 Delegate_第5张图片

完成绑定工作后我们到gamemode类里做如下工作

从仿函数到std::function再到虚幻4 Delegate_第6张图片

从仿函数到std::function再到虚幻4 Delegate_第7张图片

至此我们就可以在游戏执行后,按下w键之后的log里看到如下的输出

从仿函数到std::function再到虚幻4 Delegate_第8张图片

Enjoy it!!

你可能感兴趣的:(游戏开发;,虚幻4,游戏开发)