// 定义一个委托类型(定义卡比可以获得什么样的能力)
public delegate void AttackAction(float power);
// 创建委托实例(卡比本身)
AttackAction attackDelegate;
// 各种可能的方法(各种能力)
void FireAttack(float power) { /* 发射火球 */ }
void IceAttack(float power) { /* 释放冰块 */ }
void SwordAttack(float power) { /* 挥舞宝剑 */ }
// 委托引用某个方法(卡比吸入某个敌人)
attackDelegate = FireAttack; // 卡比获得火焰能力
// 调用委托(卡比使用当前能力)
attackDelegate(1.5f); // 使用火焰能力
// 改变委托引用(卡比吸入新敌人)
attackDelegate = IceAttack; // 卡比获得冰冻能力
// 再次调用委托(卡比使用新能力)
attackDelegate(1.5f); // 使用冰冻能力
但是和星之卡比不同的是,委托可以是多播的,它可以通过 += 和 -= 操作符吞下或者移除很多方法,然后同时具有这些方法的能力。这样子比较类似于林克在王国之泪中打下神庙可以有的英杰之力。
// 定义一个委托类型
public delegate void SuperPower(float intensity);
// 创建委托实例
SuperPower powers = null;
// 添加多个方法
powers += FireAttack; // 添加火焰能力
powers += IceAttack; // 添加冰冻能力
powers += LightningAttack; // 添加闪电能力
// 调用委托时,会按添加顺序依次执行所有方法
powers?.Invoke(2.0f); // 依次使用火焰、冰冻和闪电能力
// 第二种调用办法
if (delVal != null)
{
powers(2.0f);
}
在 Publisher - Subscriber 模式下,作为 Publisher 的 event 和作为 Subscriber 的 event handler 互相配合,创建低耦合的代码。
event 维护一个私有的 delegate。event 只具备增减 handlers 和被触发的操作。当 event 被触发时,其 invoke 其中的 delegate,然后依次调用 invocation list 中的方法:
// 逢七必过
delegate void Handler(int number); // define event
class SevenGame
{
public event Handler achor; // declare event
public void Start()
{
for (int i = 0; i != 100; i++)
{
if (i % 7 == 0 || i % 10 == 7)
{
achor?.Invoke(i); // invoke event
continue;
}
Console.WriteLine(i);
}
}
}
class Seven
{
void divSeven(int num)
{
if (num % 7 == 0)
{
Console.WriteLine($"{num}: 可以被七整除");
}
}
void isSeven(int num)
{
if (num % 10 == 7)
{
Console.WriteLine($"{num}: 中间有七");
}
}
public Seven(SevenGame game)
{
// initialize: invoking list
game.achor += isSeven;
game.achor += divSeven;
}
}
class Program
{
static void Main(string[] args)
{
SevenGame game = new SevenGame();
Seven playSeven = new Seven(game);
game.Start();
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
[System.Serializable]
public class EventVector3 : UnityEvent<Vector3> {} // define event
public class MouseManager : MonoBehaviour
{
private RaycastHit hitInfo;
// declare event
public EventVector3 onMouseClick;
private void Update()
{
SetCursorTexture();
MouseControl();
}
// 进行射线检测,返回值 hitInfo(预先声明)
void SetCursorTexture()
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hitInfo))
{
// ...
// 切换鼠标贴图
}
}
// if 鼠标点击为地面,触发事件
void MouseControl()
{
if (Input.GetMouseButtonDown(0) && hitInfo.collider != null)
{
if (hitInfo.collider.gameObject.CompareTag("Ground"))
{
onMouseClick.Invoke(hitInfo.point); // invoke envent
}
}
}
}