1.Action委托
1、Action简介:
C#中与预定义了一个委托类型Action 它默认可以指向一个没有返回值,没有参数的方法。
代码语言:javascript复制 public Action hit;
// 委托原型 = 上面的Action hit
public delegate void hitHand();
public hitHand hit;
2、Action基本使用
代码语言:javascript复制static void printString(){
Console.WriteLine("Hello World");
}
static void Main(String[] args){
Action a = printString;
a(); // 输出结果 Hello World
}
Action
其他使用方法
3、Action指向有参数的方法
代码语言:javascript复制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>指定返回值
代码语言:javascript复制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使用委托方法
观察者模式
代码语言:javascript复制案例中,场景脚本为发布者,三个物体为观察者。
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();
}
}
}
}
代码语言:javascript复制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项目中的点击箱子:
多个发布者,一个观察者
捡箱子
代码语言:javascript复制案例中:每个箱子都是发布者,而角色身上的脚本就是观察者。通过监听箱子的委托,来达到拾取箱子的目的。
// 箱子身上挂在的脚本
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);
}
}
}
代码语言:javascript复制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);
}
}
}
代码语言:javascript复制// ========================================================
// 描述:
// 作者:雷潮
// 创建时间: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 "个箱子");
}
}