Unity3D-委托使用

C#

浏览数:69

2019-8-30

1.Action委托

1、Action简介:

C#中与预定义了一个委托类型Action
它默认可以指向一个没有返回值,没有参数的方法。

    public Action hit;
// 委托原型 = 上面的Action hit
    public delegate void hitHand();
    public hitHand hit;

2、Action基本使用
static void printString(){
  Console.WriteLine("Hello World");
}

static void Main(String[] args){
  Action a = printString;
  a(); // 输出结果  Hello World
}

Action其他使用方法

3、Action指向有参数的方法
static void printNumber(int x){
    Console.WriteLine(x);
}

static void Main(String[] args){
  Action<int> a = printNumber; // 定义一个指向 形参为int的函数
  a(5); // 输出结果  5
}

Action可以通过泛型来指定,指向的方法有 0 – 16个参数

Action<int, int, string, bool 等等>

2.Func委托

  • 1.简介

Func 也是C#预定义的委托, 且可以指向带有一个返回值的方法,传递0-16个参数。

与Action区别:
Action 不能指向有返回值的方法 , 不能有返回值 。Func 可以指向有一个返回值的方法, 且必须有返回值。
For Example

1>指定返回值
static int GetNumber()
{
    return 1;
}

static void Main(string[] args)
{
 Func<int> a = GetNumber; // 定义一个Func 委托,  指向一个返回int类型的 方法
 Console.WriteLine(a());
}
2>指定参数和返回值的例子

Func<string, int>最后一个参数表示返回值类型,前面的都是形参类型。

static int Test2(string str){
  return 1;
}

static void Main(string[] args){
 Func<string, int> a = Test2; // 泛型中最后一个参数表示返回值类型。
 Console.WriteLine(a("a"));
}

  • Unity使用委托方法

    观察者模式

案例中,场景脚本为发布者,三个物体为观察者。

public class ActionManager : MonoBehaviour {

    public static ActionManager instance;
    public Action hit;
    private void Awake()
    {
        instance = this;
    }
    

    void Update () {
        if (Input.GetMouseButtonDown(0)) {
            if (hit != null)
            {
                Debug.Log("点解了");
                hit();
            }
        }
    }
}

using UnityEngine;

public class ActionTest : MonoBehaviour {
    void Start () {
        ActionManager.instance.hit += Onchange;
    }

    private void Onchange()
    {
        //Debug.Log(go.name);
        transform.localScale = new Vector3(UnityEngine.Random.Range(1,3.5f),UnityEngine.Random.Range(1, 3.5f), UnityEngine.Random.Range(1, 3.5f));
    }

    private void OnDestroy()
    {
        ActionManager.instance.hit -= Onchange;
    }
  • Unity项目中的点击箱子:

    多个发布者,一个观察者
    捡箱子

案例中:每个箱子都是发布者,而角色身上的脚本就是观察者。通过监听箱子的委托,来达到拾取箱子的目的。

// 箱子身上挂在的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoxController : MonoBehaviour {

    public System.Action<GameObject> OnHit;

    public void Hit()
    {
        if (OnHit != null)
        {
            OnHit(gameObject);
        }
    }       
}
using UnityEngine;

public class RoleCtrl : MonoBehaviour {

   void Update () {
        if (Input.GetMouseButtonUp(1))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;
            // 发射射线,检测名称为Box的layer层。
            if (Physics.Raycast(ray, out hit, Mathf.Infinity, 1 << LayerMask.NameToLayer("Box")))
            {
                BoxController box = hit.collider.GetComponent<BoxController>();
                if (box != null)
                {
                    box.Hit();
                }
                Debug.Log("find box" + hit.collider.name);

            }
      }
}
// ========================================================
// 描述:
// 作者:雷潮 
// 创建时间:2019-01-22 16:27:54
// 版 本:1.0
//========================================================
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScenneCtrl : MonoBehaviour {

    [SerializeField]
    private Transform transBox;
    [SerializeField]
    private Transform parentBox;

    private GameObject boxPrefab;
    private int minCount = 0;
    private int maxCount = 10;

    private float nextCloneTime = 0;
   

    // 数据存储
    private string boxKey = "BoxKey";
    private int getBoxCount;

    void Start () {
        boxPrefab = Resources.Load("BoxPrefabs/Box") as GameObject;
        getBoxCount = PlayerPrefs.GetInt(boxKey,0);
    }
    
    // Update is called once per frame
    void Update () {
        if (minCount < maxCount)
        {
            if (Time.time > nextCloneTime)
            {
                nextCloneTime = Time.time + 3f;
                GameObject cloneObj =   Instantiate(boxPrefab);
                cloneObj.transform.parent = parentBox;
                cloneObj.transform.position = transBox.TransformPoint(new Vector3(UnityEngine.Random.Range(-0.5f,0.5f),0, UnityEngine.Random.Range(-0.5f, 0.5f)));

                BoxController box =  cloneObj.GetComponent<BoxController>();

                if (box != null)
                {
                    box.OnHit = OnHit;
                    minCount++;
                }             
            }
        }
    }

    private void OnHit(GameObject obj)
    {
        minCount--;
        getBoxCount++;
        PlayerPrefs.SetInt(boxKey, getBoxCount);
        GameObject.Destroy(obj);
        Debug.Log("拾取了" + getBoxCount + "个箱子");
    }
}

作者:雷潮