特别适用于各种解谜关卡, 成就系统,任务系统,的 通用事件处理
CheckPointHandler.cs随便挂在场景中的某个物体上 (单例模式,场景中只要有一个)
1) How To Use
CheckPoint Events是一个列表,每个元素是一个组合事件,每个组合事件包含了一个条件列表和相应触发的UnityEvent。
Event Conditions是条件列表,每个元素是一个条件信息,比如上图表示aaa和bbb分别被触发3次以上和4次以上时触发该unity event: 关闭Book和TestCheckPoint
每个CheckPoint有一个id,并且有一个值记录该checkpoint被触发了多少次,
多个CheckPoint可以共用同一个id,上面介绍的组合事件中 条件的触发次数为所有相同id的checkpoint的触发次数之和。
可以选择能否由碰撞或者点击触发,Target为碰撞触发的tag条件(必须该tag的物体碰撞到才会触发)
超过最大触发次数之后,该checkpoint将不会再触发。(并不是id的触发次数上限,而是单个checkpoint的)
2) Code
CheckPoint.cs:
using UnityEngine;[RequireComponent(typeof(Collider2D))]
public class CheckPoint : MonoBehaviour
{public string id;public int triggerCount; //触发了多少次public bool isCollisionTrigger; //由碰撞事件触发public bool isClickTrigger; //由点击事件触发public string targetTag = "Player"; //能触发此checkpoint的tagpublic int maxTriggerCount = 1; //最大触发次数public string Trigger(){if(triggerCount >= maxTriggerCount) return "";triggerCount++;CheckPointHandler.Instance.UpdateTrigger(id, triggerCount);return id;}private void OnMouseDown() {if(isClickTrigger)Trigger();}private void OnTriggerEnter2D(Collider2D other) {if(isCollisionTrigger && other.tag == targetTag)Trigger();}
}
CheckPointHandler.cs
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;[Serializable]
public class EventCondition
{public string id;public int count;
}[Serializable]
public class CheckPointEvent{public List<EventCondition> eventConditions;public UnityEvent unityEvent;
}public class CheckPointHandler : MonoSingleton<CheckPointHandler>
{public List<CheckPointEvent> checkPointEvents; //组合事件public static Dictionary<string, int> triggerHistory = new Dictionary<string, int>();public void UpdateTrigger(string id, int Count){triggerHistory[id] = Count;Debug.Log( ($"[{0}]= {1}",id, Count));CheckEvent();}public void CheckEvent(){foreach(var e in checkPointEvents){bool flag = true;foreach(var condition in e.eventConditions){if(!triggerHistory.ContainsKey(condition.id) || triggerHistory[condition.id] < condition.count) //如果没触发够指定次数,不构成条件{flag = false;break;}}if(flag)e.unityEvent.Invoke();}}
}