using CommonAI.ZoneClient; using CommonAIClient.Client; using CommonAIClient.Unity.Battle; using CommonAIClient.Unity.Utils; using CommonLang; using CommonUnity3D.MFUnity.LoadUtil; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using UnityEngine; namespace CommonAIClient.Unity { public class DefaultBattleScene : BattleScene { public DefaultBattleScene(AbstractBattle client) : base(client) { } } public class DefaultBattleFactroy : BattleFactroy { public enum LayerSetting { UI = 5, IconGenerator = 9, ColliderObject = 10, //用于隐藏遮挡玩家的场景物体 STAGE_NAV = 13, ColliderValkyrie = 16, //女武神整体 ColliderValkyriePart = 17, //女武神身体部位 } private DefaultGameObjectAdapter mGameObjectAdapter; private DefaultTerrainAdapter mTerrainAdapater; private DefaultSoundAdapter mSoundAdapter; public DefaultBattleFactroy() : base() { mGameObjectAdapter = new DefaultGameObjectAdapter(20); mTerrainAdapater = new DefaultTerrainAdapter(); mSoundAdapter = new DefaultSoundAdapter(8); } public override BattleScene CreateBattleScene(AbstractBattle battle) { return new DefaultBattleScene(battle); } public override GameObjectAdapter GameObjectAdapter { get { return mGameObjectAdapter; } } public override SoundAdapter SoundAdapter { get { return mSoundAdapter; } } public override TerrainAdapter TerrainAdapter { get { return mTerrainAdapater; } } public override int StageNavLay { get { return (int)LayerSetting.STAGE_NAV; } } public override DisplayCell CreateDisplayCell(GameObject root, string name) { return new DisplayCell(root, name); } public override ComAICell CreateComAICell(BattleScene battleScene, CommonAI.ZoneClient.ZoneObject obj) { if (obj is ZoneActor) { return new ComAIActor(battleScene, obj as ZoneActor); } else if (obj is ZoneUnit) { return new ComAIUnit(battleScene, obj as ZoneUnit); } else if (obj is ZoneItem) { return new ComAIItem(battleScene, obj as ZoneItem); } else if (obj is ZoneSpell) { return new ComAISpell(battleScene, obj as ZoneSpell); } return null; } public override void OnError(string msg) { } public override void MakeDamplingJoint(GameObject body, GameObject from, GameObject to) { //DampingJoint dj = body.transform.GetComponentInChildren(); //if (dj != null) //{ // dj.Hook(from.transform, to.transform); //} } } public class DefaultGameObjectAdapter : GameObjectAdapter { private LRUCache gCache; private GameObject mCacheNode; public DefaultGameObjectAdapter(int cacheCount) : base() { gCache = new LRUCache(cacheCount, OnCacheRemoveObject); } private GameObject CacheNode { get { if (mCacheNode == null) { mCacheNode = new GameObject("GameObjectLoaderCache"); mCacheNode.SetActive(false); } return mCacheNode; } } public override void Load(string assetBundleName, string assetName , Action callback , bool bASyncLoadAB = true, bool bASyncLoadAsset = true) { if (callback == null) { Debug.LogError("callback == null"); return; } if (string.IsNullOrEmpty(assetBundleName) || string.IsNullOrEmpty(assetName)) { Debug.LogError("string.IsNullOrEmpty(assetBundleName) || string.IsNullOrEmpty(assetName)"); callback(false, null); return; } if (gCache.ContainsKey(assetName.ToLower())) { AssetObjectExt tmp = gCache.Get(assetName.ToLower()); tmp.transform.parent = null; tmp.transform.position = Vector3.zero; tmp.transform.rotation = Quaternion.identity; tmp.transform.localScale = Vector3.one; tmp.gameObject.SetActive(true); callback(true, tmp); } else { AssetLoader loader = new AssetLoader(assetBundleName.ToLower(), assetName.ToLower() , (succ_, res_, mfab_) => { if (callback == null) return; if (!succ_) { callback(false, null); return; } UnityEngine.Object tmp = GameObject.Instantiate(res_); if (tmp is GameObject) { AssetObjectExt aoe = (tmp as GameObject).AddComponent(); aoe.name = assetName.ToLower(); aoe.AddRef(assetBundleName.ToLower(), mfab_.Version); callback(true, aoe); } else { UnityEngine.Object.DestroyImmediate(tmp, true); callback(false, null); } }, bASyncLoadAB, bASyncLoadAsset); } } public override void Unload(AssetObjectExt aoe) { if (aoe != null) { var script = aoe.gameObject.GetComponent(); aoe.gameObject.SetActive(false); aoe.transform.parent = CacheNode.transform; gCache.Add(aoe.name, aoe); } } public void ClearCache() { gCache.Clear(); } private void OnCacheRemoveObject(AssetObjectExt aoe) { if (aoe == null || aoe.gameObject.Equals(null)) { Debug.LogWarning("remove error: null"); } else { aoe.Destroy(); } } } public class DefaultAudio : Audio { public string Name { get; set; } public AudioSource AudioSource { get; private set; } private static GameObject mSoundRoot; private static GameObject SoundRoot { get { if (mSoundRoot == null) { mSoundRoot = new GameObject("SoundRoot"); mSoundRoot.SetActive(false); } return mSoundRoot; } } public DefaultAudio() : base() { GameObject sound = new GameObject("Sound3D"); this.AudioSource = sound.AddComponent(); } public void Play() { this.AudioSource.gameObject.name = Name; this.AudioSource.gameObject.Parent(null); this.AudioSource.gameObject.SetActive(true); if (this.AudioSource.clip != null) { this.AudioSource.Play(); } } public void Stop() { this.AudioSource.Stop(); this.AudioSource.clip = null; this.AudioSource.gameObject.Parent(SoundRoot); this.AudioSource.gameObject.SetActive(false); } } public class SoundLoader { private bool mDisposed; private string mAssetBundleName; private AudioClip mAudioClip; private System.Action mCallbacks; private bool mLoadFinished; public string AssetBundleName { get { return mAssetBundleName; } } public void Load(System.Action callback) { if (mLoadFinished) { callback(mAudioClip != null, mAudioClip); return; } mCallbacks += callback; } public void Dispose() { if (!mDisposed) { mDisposed = true; if (mAudioClip != null) { UnityEngine.Object.DestroyImmediate(mAudioClip, true); mAudioClip = null; } if (mCallbacks != null) { mCallbacks(false, null); mCallbacks = null; } } } public SoundLoader(string assetBundleName) { mAssetBundleName = assetBundleName.ToLower(); AssetLoader loader = new AssetLoader(mAssetBundleName , System.IO.Path.GetFileNameWithoutExtension(mAssetBundleName) , (succ_, res_, mfab_) => { OnLoadAssetFinish(succ_, res_, mfab_); }, true, true); } private void OnLoadAssetFinish(bool succ, UnityEngine.Object res, MFUnityAssetBundle mfab) { if (succ) { mAudioClip = res as AudioClip; MFUnityAssetBundleManager.GetInstance().UnloadAssetBundleImmediate(mAssetBundleName, false); } if (mCallbacks != null) { mCallbacks(mAudioClip != null, mAudioClip); mCallbacks = null; } mLoadFinished = true; } } public class DefaultSoundAdapter : SoundAdapter { private ObjectPool mAudioPoool = new ObjectPool(); private List mLoopAudios = new List(); private Queue mNormalAudios = new Queue(); private int mMaxNormalAudioNum; private HashMap mAudioLoaders = new HashMap(); private DefaultAudio mBGM; private SoundLoader mBGMLoader; public override void Clear() { foreach (var elem in mAudioLoaders) { elem.Value.Dispose(); } mAudioLoaders.Clear(); } private void RemoveLoader(string name) { SoundLoader loader = mAudioLoaders.RemoveByKey(name.ToLower()); if (loader != null) { loader.Dispose(); } } private DefaultAudio GetNormalAudio() { DefaultAudio audio = null; if (mNormalAudios.Count >= mMaxNormalAudioNum) { audio = mNormalAudios.Dequeue(); audio.Stop(); mAudioPoool.Release(audio); } audio = mAudioPoool.Get(); mNormalAudios.Enqueue(audio); return audio; } public DefaultSoundAdapter(int maxNormalAudioNum) : base() { mMaxNormalAudioNum = maxNormalAudioNum; } private void LoadBGM(string name, System.Action callback) { if (mBGMLoader != null) { if (mBGMLoader.AssetBundleName == name.ToLower()) { mBGMLoader.Load(callback); return; } mBGMLoader.Dispose(); } mBGMLoader = new SoundLoader(name); mBGMLoader.Load(callback); } private void LoadAudio(string name, System.Action callback) { SoundLoader loader = null; if (mAudioLoaders.TryGetValue(name.ToLower(), out loader)) { if (callback != null) { loader.Load(callback); } return; } loader = new SoundLoader(name); loader.Load(callback); mAudioLoaders.Add(name.ToLower(), loader); } public override void PlayBGM(string name) { if (!string.IsNullOrEmpty(name)) { LoadBGM(name, (succ_, res_) => { if (succ_) { if (mBGM == null) { mBGM = mAudioPoool.Get(); GameObject.DontDestroyOnLoad(mBGM.AudioSource.gameObject); } mBGM.Stop(); RemoveLoader(mBGM.Name); mBGM.Name = name; mBGM.AudioSource.clip = res_; mBGM.AudioSource.loop = true; mBGM.AudioSource.volume = 1f; mBGM.AudioSource.spatialBlend = 0f; mBGM.Play(); } }); } } public override void PlaySound(string name, Vector3 pos, float distance = 20f) { LoadAudio(name, (succ_, res_) => { if (succ_) { DefaultAudio audio = GetNormalAudio(); audio.Name = name; audio.AudioSource.gameObject.Position(pos); audio.AudioSource.clip = res_; audio.AudioSource.loop = false; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script == null) { script = audio.AudioSource.gameObject.AddComponent(); } script.Auido = audio; script.Duration = audio.AudioSource.clip.length; script.TraceTarget = null; audio.Play(); } }); } public override void PlaySound(string name, int timeMS, Vector3 pos, float distance = 20f) { LoadAudio(name, (succ_, res_) => { if (succ_) { DefaultAudio audio = GetNormalAudio(); audio.Name = name; audio.AudioSource.gameObject.Position(pos); audio.AudioSource.clip = res_ as AudioClip; audio.AudioSource.loop = true; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script == null) { script = audio.AudioSource.gameObject.AddComponent(); } script.Auido = audio; script.Duration = timeMS / 1000f; script.TraceTarget = null; audio.Play(); } }); } public override Audio PlaySoundLoop(string name, Vector3 pos, float distance = 20f) { DefaultAudio audio = mAudioPoool.Get(); LoadAudio(name, (succ_, res_) => { int index = mLoopAudios.IndexOf(audio); if (index == -1) { return; } if (succ_) { audio.Name = name; audio.AudioSource.gameObject.Position(pos); audio.AudioSource.clip = res_ as AudioClip; audio.AudioSource.loop = true; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script != null) { GameObject.Destroy(script); } audio.Play(); } }); return audio; } public override void PlaySound(string name, GameObject obj, float distance = 20f) { LoadAudio(name, (succ_, res_) => { if (succ_) { DefaultAudio audio = GetNormalAudio(); audio.Name = name; audio.AudioSource.gameObject.Position(obj.Position()); audio.AudioSource.clip = res_ as AudioClip; audio.AudioSource.loop = false; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script == null) { script = audio.AudioSource.gameObject.AddComponent(); } script.Auido = audio; script.Duration = audio.AudioSource.clip.length; script.TraceTarget = obj; audio.Play(); } }); } public override void PlaySound(string name, int timeMS, GameObject obj, float distance = 20f) { LoadAudio(name, (succ_, res_) => { if (succ_) { DefaultAudio audio = GetNormalAudio(); audio.Name = name; audio.AudioSource.gameObject.Position(obj.Position()); audio.AudioSource.clip = res_ as AudioClip; audio.AudioSource.loop = true; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script == null) { script = audio.AudioSource.gameObject.AddComponent(); } script.Auido = audio; script.Duration = timeMS / 1000f; script.TraceTarget = obj; audio.Play(); } }); } public override Audio PlaySoundLoop(string name, GameObject obj, float distance = 20f) { DefaultAudio audio = GetNormalAudio(); LoadAudio(name, (succ_, res_) => { int index = mLoopAudios.IndexOf(audio); if (index == -1) { return; } if (succ_) { audio.Name = name; audio.AudioSource.gameObject.Position(obj.Position()); audio.AudioSource.clip = res_ as AudioClip; audio.AudioSource.loop = true; audio.AudioSource.volume = 1f; audio.AudioSource.spatialBlend = 0.9f; audio.AudioSource.maxDistance = distance; AudioAutoStop script = audio.AudioSource.gameObject.GetComponent(); if (script != null) { GameObject.Destroy(script); } audio.Play(); } }); return audio; } public override void StopSoundLoop(Audio sound) { DefaultAudio audio = sound as DefaultAudio; if (audio != null) { int index = mLoopAudios.IndexOf(sound as DefaultAudio); if (index != -1) { mLoopAudios.Remove(audio); } audio.Stop(); mAudioPoool.Release(audio); } } } public class DefaultTerrainAdapter : TerrainAdapter { private string mAssetBundleName; private string mAsssetName; private AssetLoader mAssetLoader; private System.Action mCallback; private GameObject mMapRoot; public override void Load(string assetBundleName, System.Action callback) { if (!string.IsNullOrEmpty(assetBundleName) && callback != null) { mMapRoot = new GameObject("MapNode"); mAssetBundleName = assetBundleName; mAsssetName = Path.GetFileNameWithoutExtension(mAssetBundleName); mCallback = callback; mAssetLoader = new AssetLoader(mAssetBundleName, mAsssetName, OnLoadFinish, false, false); } } protected virtual void OnLoadFinish(bool succ, UnityEngine.Object res, MFUnityAssetBundle ab) { if (ab == null) { mCallback(false, null); return; } GameObject map = GameObject.Instantiate(res) as GameObject; map.transform.parent = mMapRoot.transform; LoadLightmap(ab); LoadNav(ab); Transform statics = mMapRoot.transform.Find("static"); if (statics != null) { StaticBatchingUtility.Combine(statics.gameObject); } // fog settings InitFogParam(mMapRoot); // camera effect? GameObject objA = GameObject.Find("filter_a"); GameObject objB = GameObject.Find("filter_b"); if (objA != null && objB != null) { objA.transform.parent = Camera.main.gameObject.transform; objB.transform.parent = Camera.main.gameObject.transform; //position objA.transform.localPosition = new Vector3(0, 0, 0.24f); objB.transform.localPosition = new Vector3(0, 0, 0.24f); //rotation objA.transform.localRotation = Quaternion.Euler(270, 0, 0); objB.transform.localRotation = Quaternion.Euler(270, 0, 0); //scale float scaleW = 0.04f; float scaleH = 0.0225f; objA.transform.localScale = new Vector3(scaleW, 1, scaleH); objB.transform.localScale = new Vector3(scaleW, 1, scaleH); } mAssetLoader.ForeachDepFile((file) => { if (file.IndexOf("shaderslist") == -1) { MFUnityAssetBundleManager.GetInstance().UnloadAssetBundleImmediate(file, false, true); } }); MFUnityAssetBundleManager.GetInstance().UnloadAssetBundleImmediate(mAssetBundleName, false, true); mCallback(true, mMapRoot); } protected virtual bool InitFogParam(GameObject mMapRoot) { // FogAmbientColorSetting fs = mMapRoot.GetComponent(); // if (null != fs && fs.fog) // { // RenderSettings.fog = true; // RenderSettings.fogColor = fs.fogColor; // RenderSettings.fogDensity = fs.fogDensity; // RenderSettings.fogMode = fs.fogMode; // } // else // { // RenderSettings.fog = false; // } return false; } private void LoadLightmap(MFUnityAssetBundle ab) { List lms = new List(); int count = 0; UnityEngine.Object lightMapObj; do { string reslight = "Lightmap-" + count + "_comp_light"; lightMapObj = ab.AssetBundle.LoadAsset(reslight); if (lightMapObj != null) { lms.Add(lightMapObj); ++count; } else { break; } } while (true); if (lms.Count > 0) { LightmapSettings.lightmapsMode = LightmapsMode.NonDirectional; UnityEngine.LightmapData[] lmDataSet = new UnityEngine.LightmapData[lms.Count]; for (int i = 0; i < lms.Count; i++) { Texture2D tex = lms[i] as Texture2D; if (tex != null) { UnityEngine.LightmapData lmData = new UnityEngine.LightmapData(); lmData.lightmapFar = (Texture2D)tex; lmDataSet[i] = lmData; } } LightmapSettings.lightmaps = lmDataSet; } InitLightMapParam(mMapRoot); } protected virtual bool InitLightMapParam(GameObject mMapRoot) { // LightmapParam[] lmd = mMapRoot.GetComponentsInChildren(true); // for (int i = 0; i < lmd.Length; i++) // { // Renderer r = lmd[i].gameObject.GetComponent(); // r.gameObject.isStatic = true; // r.lightmapIndex = lmd[i].lightmapIndex; // r.lightmapScaleOffset = lmd[i].lightmapScaleOffset; // } return false; } private void LoadNav(MFUnityAssetBundle ab) { string resnav = mAsssetName + "_nav"; UnityEngine.Object navObj = ab.AssetBundle.LoadAsset(resnav); if (navObj != null) { GameObject nav = (GameObject)GameObject.Instantiate(navObj); nav.layer = BattleFactroy.Instance.StageNavLay; nav.transform.parent = mMapRoot.transform; foreach (Transform e in nav.GetComponentInChildren()) { MeshCollider bc = e.gameObject.GetComponent(); if (bc == null) { bc = e.gameObject.AddComponent(); } bc.gameObject.layer = nav.layer; } } } } }