using UnityEngine; using CommonAIClient.Client; using System; using CommonAI.ZoneClient; using CommonLang; using CommonLang.Concurrent; using CommonAI.Zone; using CommonAIClient.Unity.Utils; using CommonAI.Zone.ZoneEditor; namespace CommonAIClient.Unity.Battle { public partial class BattleScene : IDisposable { #region RefCount private static AtomicInteger s_alloc_count = new AtomicInteger(0); private static AtomicInteger s_active_count = new AtomicInteger(0); /// /// 分配实例数量 /// public static int AllocCount { get { return s_alloc_count.Value; } } /// /// 未释放实例数量 /// public static int ActiveCount { get { return s_active_count.Value; } } #endregion private bool mDisposed = false; private AbstractBattle mBattle; protected GameObject mMapRoot; /// /// 不绑定任何东西的特效会存在在这里 /// private GameObject mEffectRoot; public bool IsDisposed { get { return mDisposed; } } protected AbstractBattle Battle { get { return mBattle; } } protected GameObject MapRoot { get { return mMapRoot; } } public GameObject EffectRoot { get { return mEffectRoot; } } public EditorTemplates DataRoot { get { return mBattle.DataRoot; } } public ZoneInfo Terrain { get { return mBattle.Layer.Terrain; } } public SceneData SceneData { get { return this.Battle.Layer.Data; } } public int SceneID { get { return this.Battle.Layer.SceneID; } } protected BattleScene(AbstractBattle client) { s_alloc_count++; s_active_count++; mBattle = client; mBattle.Layer.LayerInit += Layer_LayerInit; mBattle.Layer.ObjectEnter += Layer_ObjectEnter; mBattle.Layer.ObjectLeave += Layer_ObjectLeave; mBattle.Layer.MessageReceived += Layer_MessageReceived; mBattle.Layer.DecorationChanged += Layer_DecorationChanged; mBattle.Layer.OnChangeBGM += Layer_OnChangeBGM; mEffectRoot = new GameObject("EffectNode"); RegistAllZoneEvent(); } ~BattleScene() { s_alloc_count--; } protected virtual void OnLoadMapFinish() { } private void OnMapLoadFinish(bool success, GameObject o) { if (success) { mMapRoot = o; InitDecoration(); } } public void Dispose() { if (!mDisposed) { OnDispose(); OnDisposeMapRoot(); mDisposed = true; s_active_count--; } } protected virtual void OnDisposeMapRoot() { GameObject.DestroyObject(mMapRoot); } protected virtual void OnDispose() { foreach (var elem in mBattleObjects) { elem.Value.Dispose(); } mBattleObjects.Clear(); mBattle.Layer.LayerInit -= Layer_LayerInit; mBattle.Layer.ObjectEnter -= Layer_ObjectEnter; mBattle.Layer.ObjectLeave -= Layer_ObjectLeave; mBattle.Layer.DecorationChanged -= Layer_DecorationChanged; AssetObjectExt[] aoes = mEffectRoot.GetComponentsInChildren(); foreach (var elem in aoes) { EffectAutoDestroy[] scripts = elem.gameObject.GetComponents(); if (scripts.Length > 0) { foreach (var script in scripts) { script.DoDestroy(); } } else { BattleFactroy.Instance.GameObjectAdapter.Unload(elem); } } GameObject.DestroyObject(mEffectRoot); } public void Update(float deltaTime) { if (!mDisposed) { OnUpdate(deltaTime); } } protected virtual void OnUpdate(float deltaTime) { foreach (var elem in mBattleObjects) { elem.Value.Update(deltaTime); } } #region Objects private HashMap mBattleObjects = new HashMap(); private IComAIActor mActor; public ComAICell GetBattleObject(uint id) { ComAICell outVal = null; mBattleObjects.TryGetValue(id, out outVal); return outVal; } public IComAIActor GetActor() { return mActor; } private void AddBattleObject(ComAICell obj) { if (obj != null) { mBattleObjects.Add(obj.ObjectID, obj); if (obj is ComAIActor) { mActor = obj as ComAIActor; } OnComAICellAdded(obj); } } private void RemoveBattleObject(uint id) { ComAICell outVal = mBattleObjects.RemoveByKey(id); if (outVal != null) { OnComAICellRemoved(outVal); outVal.Dispose(); } } protected virtual void OnComAICellAdded(ComAICell o) { } protected virtual void OnComAICellRemoved(ComAICell o) { } protected virtual void Layer_LayerInit(ZoneLayer layer) { BattleFactroy.Instance.TerrainAdapter.Load(layer.Data.FileName, OnMapLoadFinish); BattleFactroy.Instance.SoundAdapter.PlayBGM(layer.Data.BGM); } private void Layer_ObjectEnter(CommonAI.ZoneClient.ZoneLayer layer, CommonAI.ZoneClient.ZoneObject obj) { AddBattleObject(BattleFactroy.Instance.CreateComAICell(this, obj)); } private void Layer_ObjectLeave(CommonAI.ZoneClient.ZoneLayer layer, CommonAI.ZoneClient.ZoneObject obj) { RemoveBattleObject(obj.ObjectID); } #endregion private void Layer_MessageReceived(ZoneLayer layer, CommonLang.Protocol.IMessage msg) { if (msg is CommonAI.Zone.ZoneEvent) { Action action = null; if (mZoneEvens.TryGetValue(msg.GetType(), out action)) { action(msg as CommonAI.Zone.ZoneEvent); } } else if (msg is CommonAI.Zone.ObjectEvent) { var obj = GetBattleObject((msg as CommonAI.Zone.ObjectEvent).object_id); if (obj != null) { obj.DoObjectEvent(msg as CommonAI.Zone.ObjectEvent); } } } private void Layer_OnChangeBGM(ZoneLayer layer, string filename) { BattleFactroy.Instance.SoundAdapter.PlayBGM(filename); } public virtual void PlayEffectWithZoneCoord(LaunchEffect eff , float x, float y, float direct) { Vector3 pos = Extensions.ZonePos2NavPos(mBattle.Layer.Terrain.TotalHeight , x, y, 0); Quaternion rot = Extensions.ZoneRot2UnityRot(direct); if (eff != null) { if (!string.IsNullOrEmpty(eff.SoundName)) { if (eff.IsLoop) { BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, eff.EffectTimeMS, pos); } else { BattleFactroy.Instance.SoundAdapter.PlaySound(eff.SoundName, pos); } } //特效 if (!string.IsNullOrEmpty(eff.Name)) { BattleFactroy.Instance.GameObjectAdapter.Load(eff.Name , System.IO.Path.GetFileNameWithoutExtension(eff.Name) , (succ, aoe) => { if (succ) { if (IsDisposed && eff.BindBody) { BattleFactroy.Instance.GameObjectAdapter.Unload(aoe); return; } OnLoadEffectSuccess(aoe, eff, pos, rot); } }); } } } /// /// /// /// /// unity pos /// unity rot public virtual void PlayEffect(LaunchEffect eff, Vector3 pos, Quaternion rot) { if (eff != null) { //特效 if (!string.IsNullOrEmpty(eff.Name)) { BattleFactroy.Instance.GameObjectAdapter.Load(eff.Name , System.IO.Path.GetFileNameWithoutExtension(eff.Name) , (succ, aoe) => { if (succ) { if (IsDisposed && eff.BindBody) { BattleFactroy.Instance.GameObjectAdapter.Unload(aoe); return; } OnLoadEffectSuccess(aoe, eff, pos, rot); } }); } } } protected virtual void OnLoadEffectSuccess(AssetObjectExt aoe , LaunchEffect eff, Vector3 pos, Quaternion rot) { aoe.gameObject.Parent(mEffectRoot); aoe.gameObject.Position(pos); aoe.gameObject.Rotation(rot); var script = aoe.gameObject.AddComponent(); script.aoeHandler = aoe; script.duration = eff.IsLoop ? eff.EffectTimeMS / 1000f : 0f; } } }