using Convention; using Demo.Game.Attr; using Demo.Game.ConfigType; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; namespace Demo.Game { namespace ConfigType { public class SkyUpdatementConfig : UpdatementIntConfig { public string SkyAssetBundlePath; public string[] SkyNames; public int[] SkyIndexs; public override void Deserialize(BinaryReader reader) { SkyAssetBundlePath = BinarySerializeUtility.ReadString(reader); SkyNames = BinarySerializeUtility.DeserializeStringArray(reader); SkyIndexs = BinarySerializeUtility.DeserializeIntArray(reader); base.Deserialize(reader); var sky = (SkyUpdatement)target; sky.Load(SkyAssetBundlePath); for (int i = 0, e = SkyNames.Length; i < e; i++) { sky.NameCache.Add(SkyNames[i], SkyIndexs[i]); sky.IndexCache.Add(SkyIndexs[i], SkyNames[i]); sky.SkyAssetBundleLoaderStatus++; IEnumerator Foo() { yield return new WaitUntil(() => sky.SkyAssetBundle != null); var ir = sky.SkyAssetBundle.LoadAssetAsync(SkyNames[i]); ir.completed += delegate { var mat = ir.asset as Material; sky.MaterialCache[SkyIndexs[i]] = mat; sky.SkyAssetBundleLoaderStatus--; }; yield return ir; } ConventionUtility.StartCoroutine(Foo()); } } public override void Serialize(BinaryWriter writer) { BinarySerializeUtility.WriteString(writer, SkyAssetBundlePath); var sky = (SkyUpdatement)target; int e = sky.NameCache.Count; SkyNames =new string[e]; SkyIndexs=new int[e]; int i = 0; foreach (var item in sky.NameCache) { SkyNames[i] = item.Key; SkyIndexs[i] = item.Value; } BinarySerializeUtility.SerializeArray(writer, SkyNames); BinarySerializeUtility.SerializeArray(writer, SkyIndexs); base.Serialize(writer); } } } [Scriptable] public class SkyUpdatement : Updatement, IAssetBundleLoader { protected override ScriptLoadableConfig MakeConfig() { return new SkyUpdatementConfig(); } public static SkyUpdatement Make() { return new GameObject().AddComponent(); } internal int SkyAssetBundleLoaderStatus = 0; internal readonly Dictionary NameCache = new(); internal readonly Dictionary IndexCache = new(); internal readonly Dictionary MaterialCache = new(); public string SkyAssetBundlePath { get => GetConfig().SkyAssetBundlePath; set => GetConfig().SkyAssetBundlePath = value; } public AssetBundle SkyAssetBundle; protected override int Lerp(int begin, int end, float t) { return begin; } [Content, SerializeField] private int Cache = -1; protected override IEnumerator DoSomethingDuringApplyScript() { yield return base.DoSomethingDuringApplyScript(); yield return new WaitUntil(() => SkyAssetBundleLoaderStatus == 0); } protected override void UpdateData(int data) { if (string.IsNullOrEmpty(SkyAssetBundlePath)) return; if (Cache != data) { if (data < 0) RenderSettings.skybox = null; else RenderSettings.skybox = MaterialCache[data]; Cache = data; } } public override IEnumerator UnloadScript() { Cache = -1; if (string.IsNullOrEmpty(SkyAssetBundlePath) == false) yield return this.UnloadAssetBundle(SkyAssetBundlePath); SkyAssetBundlePath = ""; yield return base.UnloadScript(); } /// /// 对应ab包名称,自动匹配对应平台 /// /// [Convention.RScript.Variable.Attr.Method] public void Load(string ab) { SkyAssetBundleLoaderStatus++; ConventionUtility.StartCoroutine(this.LoadAssetBundle(ab, x => { SkyAssetBundlePath = ab; SkyAssetBundle = x; SkyAssetBundleLoaderStatus--; })); } /// /// 在指定时刻切换天空 /// /// /// [Convention.RScript.Variable.Attr.Method] public void Add(float time, string sky) { IEnumerator Foo() { yield return new WaitUntil(() => SkyAssetBundle != null); var ir = SkyAssetBundle.LoadAssetAsync(sky); ir.completed += delegate { var mat = ir.asset as Material; if (NameCache.TryGetValue(sky, out int id) == false) { id = NameCache.Count; NameCache[sky] = id; IndexCache[id] = sky; } MaterialCache[id] = mat; ManualAddEntry(time, id, default); SkyAssetBundleLoaderStatus--; }; yield return ir; } SkyAssetBundleLoaderStatus++; ConventionUtility.StartCoroutine(Foo()); } } }