关于 UE4 委托写法

Posted Suozhiyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于 UE4 委托写法相关的知识,希望对你有一定的参考价值。

 

Source\\CoinCollector\\DelegateActor.h

 // Fill out your copyright notice in the Description page of Project Settings.
 
 #pragma once
 
 #include "CoreMinimal.h"
 #include "GameFramework/Actor.h"
 #include "DelegateActor.generated.h"
 
 // 声明一个没有参数,没有返回值的委托
 DECLARE_DELEGATE(FNoParamNoReturn);
 // 带参数的委托,给与参数时只需要指定类型
 DECLARE_DELEGATE_OneParam(FParam1NoReturn, const FString&);
 DECLARE_DELEGATE_TwoParams(FParam2NoReturn, const FString&, float);
 // 带参数,并且有返回值的委托
 DECLARE_DELEGATE_RetVal_TwoParams(float, FParam2Return, const FString&, float);
 
 UCLASS()
 class COINCOLLECTOR_API ADelegateActor : public AActor
 
     GENERATED_BODY()
     
 public:    
     // Sets default values for this actor\'s properties
     ADelegateActor();
 
 protected:
     // Called when the game starts or when spawned
     virtual void BeginPlay() override;
 
 public:    
     // Called every frame
     virtual void Tick(float DeltaTime) override;
 
 public:
     FNoParamNoReturn DelegateNoParamNoReturn;            // 使用声明过的委托名称定义一个委托对象
     FParam1NoReturn DelegateOneParamNoReturn;
     FParam2NoReturn DelegateTwoParamNoReturn;
     FParam2Return DelegateTwoParamReturn;
 
 private:
     // 没有参数和返回值的委托函数
     void TestNoParamNoReturn();        
     // 带一个参数和没有返回值的委托函数
     void TestOneParamNoReturn(const FString&);
     // 带两个参数和没有返回值的委托函数
     void TestTwoParamNoReturn(const FString&, float);
     // 带两个参数和 Float 返回值的委托函数
     float TestTwoParamReturn(const FString&, float);
 
 private:
     float TimerMax = 3.f;
     float TimerCount = 0;
 ;

 

Source\\CoinCollector\\DelegateActor.cpp

 // Fill out your copyright notice in the Description page of Project Settings.
 
 #include "DelegateActor.h"
 #include "MoveActor.h"
 #include "NewTypes.h"
 
 // Sets default values
 ADelegateActor::ADelegateActor()
 
      // 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 ADelegateActor::BeginPlay()
 
     Super::BeginPlay();
 
     // 对于我们需要执行的委托对象,我们需要给他指定存在的真实函数(绑定委托)
     DelegateNoParamNoReturn.BindUObject(this, &ADelegateActor::TestNoParamNoReturn);
     DelegateOneParamNoReturn.BindUObject(this, &ADelegateActor::TestOneParamNoReturn);
     DelegateTwoParamNoReturn.BindUObject(this, &ADelegateActor::TestTwoParamNoReturn);
     DelegateTwoParamReturn.BindUObject(this, &ADelegateActor::TestTwoParamReturn);
 
 
 // Called every frame
 void ADelegateActor::Tick(float DeltaTime)
 
     Super::Tick(DeltaTime);
 
     if (TimerCount >= TimerMax)
     
         DelegateNoParamNoReturn.ExecuteIfBound();                   // 执行委托
         DelegateOneParamNoReturn.ExecuteIfBound(TEXT("ABC"));
         DelegateTwoParamNoReturn.ExecuteIfBound(TEXT("ABC"), TimerCount);        // ExecuteIfBound 只能是执行没有返回值的委托
         if (DelegateTwoParamReturn.IsBound())
         
             TimerCount = DelegateTwoParamReturn.Execute(FString("CDE"),TimerCount);    // 执行有返回值的委托
         
         else
         
             UE_LOG(SZYLog, Display, TEXT(" DelegateTwoParamReturn.IsBound() == NULL "));
         
         UE_LOG(SZYLog, Display, TEXT("TimerCount: %f"), TimerCount);
         UE_LOG(SZYLog, Display, TEXT(" ===================== "));
         TimerCount = 0;
     
     TimerCount += DeltaTime;
 
 
 void ADelegateActor::TestNoParamNoReturn()
 
     UE_LOG(SZYLog, Display, TEXT("TestNoParamNoReturn Go!!!"));
 
 
 void ADelegateActor::TestOneParamNoReturn(const FString& Param)
 
     UE_LOG(SZYLog, Display, TEXT("TestNoParamNoReturn Go!!! FString: %s"), *Param);
 
 
 void ADelegateActor::TestTwoParamNoReturn(const FString& Param1, float Param2)
 
     UE_LOG(SZYLog, Display, TEXT("TestTwoParamNoReturn Go!!! param1: %s, param2: %f"), *Param1, Param2);
 
 
 float ADelegateActor::TestTwoParamReturn(const FString& Param1, float Param2)
 
     static float Tmp = 0;
     Tmp += Param2;
     UE_LOG(SZYLog, Display, TEXT("TestTwoParamReturn Go!!! param1: %s, param2: %f"), *Param1, Param2);
     if (Tmp >= 30.f)
     
         // 解委托
         DelegateTwoParamReturn.Unbind();
     
     return Tmp;
 

 

Delegate 多种写法总结

 

  • 委托是嘛?

 

委托是一个类型安全的对象,它指向程序中另一个以后会被调用的方法(或多个方法)。通俗的说,委托是一个可以引用方法的对象,当创建一个委托,也就创建一个引用方法的对象,进而就可以调用那个方法,即委托可以调用它所指的方法。

 

  • 如何使用委托?

 

1、定义委托类型

 

[访问修饰符]delegate 返回类型 委托名(形参);

 

2、声明委托对象

 

委托名 委托实例名;

 

3、创建委托对象(确定与哪些方法进行绑定)

 

委托实例名=new 委托名(某个类的方法)

 

4、使用委托调用方法

 

委托实例名(实参)

 

  • 委托注意事项:

 

1、委托和方法必须具有相同的参数。

 

2、委托可以调用多个方法,即一个委托对象可以维护一个可调用方法的列表而不是单独的一个方法,称为多路广播(多播)。

 

3、使用+=和-=运算实现方法的增加和减少

 

  • 示例

 

技术分享图片
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Delegate;

namespace Delegate
{

public delegate int Call(int num1, int num2);//第一步:定义委托类型
class SimpleMath
{
// 乘法方法
public int Multiply(int num1, int num2)
{
return num1 * num2;
}

// 除法方法
public int Divide(int num1, int num2)
{
return num1 / num2;
}
}
}
class Test
{
static void Main(string[] args)
{
Call objCall;//第二步:声明委托对象
// Math 类的对象
SimpleMath objMath = new SimpleMath();
// 第三步:创建委托对象,将方法与委托关联起来
objCall = new Call(objMath.Multiply);

Call objCall1 = new Call(objMath.Divide);
objCall += objCall1;//向委托增加一个方法
//objCall -= objCall1;//向委托减去一个方法
            // 调用委托实例,先执行objMath.Multiply,然后执行objMath.Divide
int result = objCall(5, 3);
System.Console.WriteLine("结果为 {0}", result);
Console.ReadKey();
}
}
 
技术分享图片

 

写法:

 

1、委托 委托名=new 委托(会调用的方法名); 委托名(参数);

 

2、委托 委托名 =会调用的方法名; 委托名(参数);

 

3、匿名方法

 

委托 委托名=delegate(参数){会调用的方法体};委托名(参数);

 

4、拉姆达表达式

 

委托 委托名=((参数1,。。参数n)=>{会调用的方法体});委托名(参数);

 

5、用Action<T>和Func<T>,第一个无返回值

 

Func<参数1, 参数2, 返回值> 委托名= ((参数1,参数2) => {带返回值的方法体 });返回值=委托名(参数1,参数2);

 

贴代码:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using @delegate;
 
namespace @delegate
{
        public delegate int Call(int num1, int num2);
        class SimpleMath
        {
            // 乘法方法
            public static int Multiply(int num1, int num2)
            {
                return num1 * num2;
            }
 
            // 除法方法
            public int Divide(int num1, int num2)
            {
                return num1 / num2;
            }
        }
    class Test
    {
        static void Main(string[] args)
        {
            //--------------------第一种写法------------------------//
            //Call objCall = new Call(SimpleMath.Multiply);
            //Call objCall1 = new Call(new SimpleMath().Divide);
            //--------------------第二种写法------------------------//
            //Call objCall = SimpleMath.Multiply;
            //Call objCall1 = new SimpleMath().Divide;
            //--------------------第三种写法------------------------//
            //Call objCall = delegate(int a, int b)
            //{
            //    return a * b;
            //};
            //Call objCall1 = delegate(int a, int b)
            //{
            //    return a / b;
            //};
            //--------------------第四种写法------------------------//
            //Call objCall =((int a,int b)=> { return a*b;});
            //Call objCall1 = ((int a, int b) => { return a / b; });
            //--------------------第五种写法------------------------//
            Func<int, int, int> objCall = ((a, b) => { return a * b; });
            Func<int, int, int> objCall1 = ((a, b) => { return a / b; });
             Action<int, int> ob = ((a, b) => { Console.WriteLine(a * b); });
             ob(5, 3);
            //----------------------------------------------------//
             int result = objCall(5, 3);
             int result1 = objCall1(5, 3);
             System.Console.WriteLine("结果1为 {0},结果2为{1}", result,result1);
            Console.ReadKey();
        }
    }
}

 

 

一、委托调用方式

1. 最原始版本:

技术分享图片
    delegate string PlusStringHandle(string x, string y);
    class Program
    {
        static void Main(string[] args)
        {
            PlusStringHandle pHandle = new PlusStringHandle(plusString);
            Console.WriteLine(pHandle("abc", "edf"));

            Console.Read();
        }

        static string plusString(string x, string y)
        {
            return x + y;
        }
    }
技术分享图片

 2. 原始匿名函数版:去掉“plusString”方法,改为

            PlusStringHandle pHandle = new PlusStringHandle(delegate(string x, string y)
            {
                return x + y;
            });
            Console.WriteLine(pHandle("abc", "edf"));

3. 使用Lambda(C#3.0+),继续去掉“plusString”方法(以下代码均不再需要该方法)

            PlusStringHandle pHandle = (string x, string y) =>
            {
                return x + y;
            };
            Console.WriteLine(pHandle("abc", "edf"));

还有更甚的写法(省去参数类型)

            PlusStringHandle pHandle = (x, y) =>
            {
                return x + y;
            };
            Console.WriteLine(pHandle("abc", "edf"));

如果只有一个参数

技术分享图片
        delegate void WriteStringHandle(string str);
        static void Main(string[] args)
        {
            //如果只有一个参数
            WriteStringHandle handle = p => Console.WriteLine(p);
            handle("lisi");

            Console.Read();
        }
技术分享图片

 

二、委托声明方式

1. 原始声明方式见上述Demo

2. 直接使用.NET Framework定义好的泛型委托 Func 与 Action ,从而省却每次都进行的委托声明。

技术分享图片
        static void Main(string[] args)
        {
            WritePrint<int>(p => Console.WriteLine("{0}是一个整数", p), 10);

            Console.Read();
        }

        static void WritePrint<T>(Action<T> action, T t)
        {
            Console.WriteLine("类型为:{0},值为:{1}", t.GetType(), t);
            action(t);
        }
技术分享图片

3. 再加上个扩展方法,就能搞成所谓的“链式编程”啦。

技术分享图片
    class Program
    {   
        static void Main(string[] args)
        {
            string str = "所有童鞋:".plusString(p => p = p + " girl: lisi、lili
").plusString(p => p + "boy: wangwu") ;
            Console.WriteLine(str);

            Console.Read();
        }
    }

    static class Extentions
    {
        public static string plusString<TParam>(this TParam source, Func<TParam, string> func)
        {
            Console.WriteLine("字符串相加前原值为:{0}。。。。。。", source);
            return func(source);
        }
    }
技术分享图片

看这个代码是不是和我们平时写的"list.Where(p => p.Age > 18)"很像呢?没错Where等方法就是使用类似的方式来实现的。

好了,我总结完了,如有遗漏,还望补上,臣不尽感激。











































以上是关于关于 UE4 委托写法的主要内容,如果未能解决你的问题,请参考以下文章

C# 委托及各种写法

Ue4_UEnum枚举类型

Delegate 多种写法总结

委托的多种写法

委托的N种写法,你喜欢哪种?

事件委托 兼容性写法