using UnityEngine; using System; using CommonLang.Concurrent; using CommonAI.Zone; using CommonLang; using CommonAIClient.Unity.Utils; namespace CommonAIClient.Unity.Battle { public partial class BattleObject : 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; private bool mActiveSelf; private BattleScene mBattleScene; private GameObject mObjectRoot; private GameObject mDisplayRoot; private GameObject mDummyRoot; private GameObject mEffectRoot; private DisplayCell mDisplayCell; private HashMap mDummys = new HashMap(); //保存最后申请的动作 private string mLastAnimName; private bool mLastCrossFade; private WrapMode mLastWrapMode; private float mLastSpeed; public bool IsDisposed { get { return mDisposed; } } protected BattleScene BattleScene { get { return mBattleScene; } } protected GameObject ObjectRoot { get { return mObjectRoot; } } public Vector3 Position { get { return this.mObjectRoot.Position(); } } protected GameObject DisplayRoot { get { return mDisplayRoot; } } protected GameObject DummyRoot { get { return mDummyRoot; } } public GameObject EffectRoot { get { return mEffectRoot; } } protected DisplayCell DisplayCell { get { return mDisplayCell; } } protected HashMap Dummys { get { return mDummys; } } public string LastAnimName { get { return mLastAnimName; } } public bool LastCrossFade { get { return mLastCrossFade; } } public WrapMode LastWrapMode { get { return mLastWrapMode; } } public float LastSpeed { get { return mLastSpeed; } } public bool ActiveSelf { get { return mActiveSelf; } set { this.mActiveSelf = value; this.ObjectRoot.SetActive(mActiveSelf); this.PlayAnim(mLastAnimName, mLastCrossFade, mLastWrapMode, mLastSpeed); } } public BattleObject(BattleScene battleScene, string name = "") { s_alloc_count++; s_active_count++; mBattleScene = battleScene; mObjectRoot = new GameObject(name); mDisplayRoot = new GameObject("DisplayRoot"); mDisplayRoot.ParentRoot(mObjectRoot); mDummyRoot = new GameObject("DummyRoot"); mDummyRoot.ParentRoot(mObjectRoot); mEffectRoot = new GameObject("EffectRoot"); mEffectRoot.ParentRoot(mObjectRoot); mDisplayCell = BattleFactroy.Instance.CreateDisplayCell(mDisplayRoot); } ~BattleObject() { s_alloc_count--; } protected virtual void CorrectDummyNode() { foreach (var elem in mDummys) { GameObject trace = mDisplayCell.GetDummyNode(elem.Key); elem.Value.Init(elem.Key, trace); } } /// /// 如果名字不为空 一定会返回一个DummyNode /// /// /// public virtual DummyNode GetDummyNode(string name) { if (string.IsNullOrEmpty(name)) { Debug.LogError("string.IsNullOrEmpty(name)"); return null; } DummyNode dummyNode = null; if (!mDummys.TryGetValue(name, out dummyNode)) { GameObject node = mDisplayCell.GetDummyNode(name); if (node == null) { Debug.LogError("node not exist " + name); } GameObject tmp = new GameObject(name); tmp.ParentRoot(mDummyRoot); dummyNode = tmp.AddComponent(); dummyNode.Init(name, node); mDummys.Add(name, dummyNode); } return dummyNode; } public virtual float GetAnimLength(string name) { if (this.DisplayCell != null) { return this.DisplayCell.GetAnimLength(name); } return 0f; } public virtual void PlayAnim(string name, bool crossFade , WrapMode wrapMode = WrapMode.Once, float speed = 1f) { if (!string.IsNullOrEmpty(name)) { mLastAnimName = name; mLastCrossFade = crossFade; mLastWrapMode = wrapMode; mLastSpeed = speed; mDisplayCell.PlayAnim(name, crossFade, wrapMode, speed); } } /// /// /// /// /// unity pos /// unity rot public virtual void PlayEffect(LaunchEffect eff, Vector3 pos, Quaternion rot) { 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); } }); } } } protected virtual void OnLoadEffectSuccess(AssetObjectExt aoe , LaunchEffect eff, Vector3 pos, Quaternion rot) { aoe.gameObject.Parent(BattleScene.EffectRoot); aoe.gameObject.Position(pos); aoe.gameObject.Rotation(rot); var script = aoe.gameObject.AddComponent(); script.aoeHandler = aoe; script.duration = eff.IsLoop ? eff.EffectTimeMS / 1000f : 0f; GameObject dummy = mEffectRoot; if (!string.IsNullOrEmpty(eff.BindPartName)) { dummy = mDisplayCell.GetDummyNode(eff.BindPartName); if (dummy == null) { dummy = mEffectRoot; } aoe.gameObject.Position(dummy.Position()); } if (eff.BindBody) { aoe.gameObject.ParentRoot(dummy); } } public void Update(float deltaTime) { if (!mDisposed) { OnUpdate(deltaTime); } } protected virtual void OnUpdate(float deltaTime) { } public void Dispose() { if (!mDisposed) { OnDispose(); mDisposed = true; s_active_count--; } } protected virtual void OnDispose() { mDisplayCell.Dispose(); AssetObjectExt[] aoes = mDummyRoot.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.Destroy(mObjectRoot); } } }