using UnityEngine; using System; using System.Collections; using System.Collections.Generic; [AddComponentMenu("Trigger/Trigger_General")] public class AreaEventTrigger : FuncRegion,ITrigger { //触发时机 public enum EActTiming { Init, Enter, // first one enters Leave, // last one leaves Update, EnterDura, } public enum ActionWhenFull { DoNothing, Destroy, } [Serializable] public struct STimingAction { public EActTiming Timing; public string HelperName; public int HelperIndex; //public TextAsset ActionFile; public string ActionName; } public struct STriggerContext { public Fighter fighter; public int token; public float updateTimer; public STriggerContext(Fighter actor , int token , float inUpdateInterval) { this.fighter = actor; this.token = token; updateTimer = inUpdateInterval; } } [FriendlyName("ID")] public int ID = 0; [FriendlyName("容量")] public int Capacity = 10; //[FriendlyName("满载动作")] public ActionWhenFull actionWhenFull = ActionWhenFull.DoNothing; [FriendlyName("存活时间【秒】")] public float AliveTicks; // total [FriendlyName("触发次数")] public int TriggerTimes; // total [FriendlyName("触发完毕后失效")] public bool bDeactivateSelf = true; [FriendlyName("探测频率【秒】")] public float UpdateInterval; [FriendlyName("轮询式探测")] public bool bSimpleUpdate = false; [FriendlyName("只有非满血才能触发")] public bool OnlyEffectNotFullHpOrMpActor = false; private Dictionary _inActorsCache = null; [FriendlyName("进入时音效")] public string EnterSound = null; [FriendlyName("离开时音效")] public string LeaveSound = null; public GameObject[] NextTriggerList = new GameObject[0]; [HideInInspector, NonSerialized] public Dictionary _inActors = new Dictionary(); private int _testToken = 0; private Fighter[] _actorTestCache; private long[] _actorTormvCache; private int m_triggeredCount; private int m_updateTimer; [HideInInspector, NonSerialized] public bool bDoDeactivating; private bool m_bShaped = false; private int m_collidedCnt = 0; public int InActorCount { get { return _inActors.Count; } } public TriggerActionWrapper[] TriggerActions = new TriggerActionWrapper[0]; [HideInInspector, NonSerialized] public TriggerActionWrapper PresetActWrapper = null; private TriggerActionWrapper[] m_internalActList = new TriggerActionWrapper[0]; public GameObject GetTriggerObj() { return gameObject; } void Awake() { _actorTormvCache = new long[Capacity]; m_updateTimer = (int)(UpdateInterval * 1000); BuildTriggerWrapper(); BuildInternalWrappers(); } private void Update() { UpdateLogic(Time.deltaTime); } void OnDestroy() { _inActorsCache = null; foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.Destroy(); } } } protected virtual void BuildTriggerWrapper() { } private void BuildInternalWrappers() { if (PresetActWrapper != null) { m_internalActList = AddElement(m_internalActList, PresetActWrapper); } if (TriggerActions.Length > 0) { m_internalActList = AppendElements(m_internalActList, TriggerActions); } foreach (TriggerActionWrapper taw in m_internalActList) { if (taw == null) { continue; } if (taw.GetActionInternal() == null) { taw.Init(ID); } } } public override void UpdateLogic(float delta) { if (!isStartup) { return; } if (bSimpleUpdate) { UpdateLogicSimple(delta); } if (AliveTicks > 0) { AliveTicks -= delta; if (AliveTicks <= 0) { AliveTicks = 0; DoSelfDeactivating(); } } } private void UpdateLogicSimple(float delta) { if (TriggerTimes > 0 && m_triggeredCount >= TriggerTimes) { return; } int iDelta = (int)(delta * 1000); m_updateTimer -= iDelta; if (m_updateTimer <= 0) { m_updateTimer =(int)(UpdateInterval * 1000); for (int i = 0; i < Capacity; ++i) { Fighter curAct = _actorTestCache[i]; DoActorUpdate(ref curAct); } if (++m_triggeredCount >= TriggerTimes && TriggerTimes > 0) { bDoDeactivating = bDeactivateSelf; } } } public void DoSelfDeactivating() { bDoDeactivating = false; int toRmvNum = 0; var etr = _inActors.GetEnumerator(); while (etr.MoveNext()) { _actorTormvCache[toRmvNum++] = etr.Current.Key; } for (int i = 0; i < toRmvNum; ++i) { long toRmvObjId = _actorTormvCache[i]; Fighter refHdl = _inActors[toRmvObjId].fighter; #region 这两行时序不能随意调换 DoActorLeave(ref refHdl); _inActors.Remove(toRmvObjId); #endregion 这两行时序不能随意调换 } DeactivateSelf(); ActivateNext(); } private void DeactivateSelf() { gameObject.SetActive(false); } private void ActivateNext() { foreach (GameObject nextGo in NextTriggerList) { if (nextGo != null) { nextGo.SetActive(true); } } } protected virtual void DoActorEnter(ref Fighter inActor) { MusicMgr.Instance.PlayFightSound(EnterSound); DoActorEnterShared(ref inActor); } protected virtual void DoActorLeave(ref Fighter inActor) { DoActorLeaveShared(ref inActor); if (inActor == null) return; if (!string.IsNullOrEmpty(LeaveSound)) { MusicMgr.Instance.PlayFightSound(LeaveSound); } } protected void DoActorEnterShared(ref Fighter inActor) { foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.TriggerEnter(inActor, this); } } } protected void DoActorLeaveShared(ref Fighter inActor) { foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.TriggerLeave(inActor, this); } } } protected virtual void DoActorUpdate(ref Fighter inActor) { DoActorUpdateShared(ref inActor); } protected void DoActorUpdateShared(ref Fighter inActor) { foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.TriggerUpdate(inActor, this); } } } public override void Startup() { base.Startup(); //_thisActor = ActorHelper.GetActorRoot(sourceActor); OnTriggerStart(); } public override void Stop() { base.Stop(); int count = m_internalActList.Length; for (int i = 0; i < count; ++i) { var taw = m_internalActList[i]; if (taw != null) { taw.Stop(); } } } protected void OnCoolingDown() { foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.OnCoolDown(this); } } } protected void OnTriggerStart() { foreach (TriggerActionWrapper taw in m_internalActList) { if (taw != null) { taw.OnTriggerStart(this); } } } public void onActorDestroy(ref Fighter f) { if (f!=null) { long id = f.Id; if (null != _inActors && _inActors.ContainsKey(id)) { DoActorLeave(ref f); _inActors.Remove(id); } if (null != _inActorsCache && _inActorsCache.ContainsKey(id)) { _inActorsCache.Remove(id); } } else { DebugHelper.LogError("onActorDestroy#prm.src == null!"); } } public static T[] AddElement(T[] elements, T element) { List elementsList = new List(elements); elementsList.Add(element); return LinqS.ToArray(elementsList); } public static T[] AppendElements(T[] elements, T[] appendElements) { List elementsList = new List(elements); if (appendElements != null) { elementsList.AddRange(appendElements); } return LinqS.ToArray(elementsList); } }