ro-webgl/Assets/Src/Triggers/AreaEventTrigger.cs
2021-12-21 09:40:39 +08:00

406 lines
9.7 KiB
C#

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<long, int> _inActorsCache = null;
[FriendlyName("进入时音效")]
public string EnterSound = null;
[FriendlyName("离开时音效")]
public string LeaveSound = null;
public GameObject[] NextTriggerList = new GameObject[0];
[HideInInspector, NonSerialized]
public Dictionary<long, STriggerContext> _inActors = new Dictionary<long, STriggerContext>();
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>(T[] elements, T element)
{
List<T> elementsList = new List<T>(elements);
elementsList.Add(element);
return LinqS.ToArray(elementsList);
}
public static T[] AppendElements<T>(T[] elements, T[] appendElements)
{
List<T> elementsList = new List<T>(elements);
if (appendElements != null)
{
elementsList.AddRange(appendElements);
}
return LinqS.ToArray(elementsList);
}
}