diff --git a/Assets/Scripts/Environment/SkyUpdatement.cs b/Assets/Scripts/Environment/SkyUpdatement.cs index ebe7014..e98aaac 100644 --- a/Assets/Scripts/Environment/SkyUpdatement.cs +++ b/Assets/Scripts/Environment/SkyUpdatement.cs @@ -1,40 +1,46 @@ using System.Collections; +using System.Collections.Generic; using Convention; using UnityEngine; namespace Demo.Game { - public class SkyUpdatement : Updatement, IAssetBundleLoader + public class SkyUpdatement : Updatement, IAssetBundleLoader { public static SkyUpdatement Make() { return new GameObject().AddComponent(); } + private readonly Dictionary NameCache = new(); + private readonly Dictionary MaterialCache = new(); + public string SkyAssetBundlePath; public AssetBundle SkyAssetBundle; - protected override Material Lerp(Material begin, Material end, float t) + protected override int Lerp(int begin, int end, float t) { return begin; } - [Content, SerializeField] private Material Cache; + [Content, SerializeField] private int Cache; - protected override void UpdateData(Material data) + protected override void UpdateData(int data) { if (string.IsNullOrEmpty(SkyAssetBundlePath)) return; + if (Cache < 0) + return; if (Cache != data) { - RenderSettings.skybox = data; + RenderSettings.skybox = MaterialCache[data]; Cache = data; } } public override IEnumerator UnloadScript() { - Cache = null; + Cache = -1; if (string.IsNullOrEmpty(SkyAssetBundlePath) == false) yield return this.UnloadAssetBundle(SkyAssetBundlePath); SkyAssetBundlePath = ""; @@ -67,7 +73,13 @@ namespace Demo.Game ir.completed += delegate { var mat = ir.asset as Material; - ManualAddEntry(time, mat, default); + if (NameCache.TryGetValue(sky, out int id) == false) + { + id = NameCache.Count; + NameCache[sky] = id; + } + MaterialCache[id] = mat; + ManualAddEntry(time, id, default); }; yield return ir; } diff --git a/Assets/Scripts/Framework/Updatement.cs b/Assets/Scripts/Framework/Updatement.cs index 5923f79..61867b9 100644 --- a/Assets/Scripts/Framework/Updatement.cs +++ b/Assets/Scripts/Framework/Updatement.cs @@ -3,11 +3,12 @@ using Demo.Editor.UI; using System; using System.Collections; using System.Collections.Generic; +using Unity.Collections; using UnityEngine; namespace Demo.Game { - public abstract class Updatement : TimelineScriptObject + public abstract class Updatement : TimelineScriptObject where DataType : struct { [Serializable] public class UpdatementEntry @@ -16,9 +17,29 @@ namespace Demo.Game public DataType Position = default; public MathExtension.EaseCurveType easeCurveType = MathExtension.EaseCurveType.Linear; } + [Serializable] + public struct UpdatementCompiledEntries + { + public NativeArray TimePoints; + public NativeArray Positions; + public NativeArray EaseCurveTypes; + public readonly int Count; + + public UpdatementCompiledEntries(NativeArray timePoints, + NativeArray positions, + NativeArray easeCurveTypes, + int count) + { + TimePoints = timePoints; + Positions = positions; + EaseCurveTypes = easeCurveTypes; + Count = count; + } + } public int Content = 0; - public readonly List Entries = new(); + private List Entries = new(); + public UpdatementCompiledEntries CompiledEntries; protected abstract void UpdateData(DataType data); protected abstract DataType Lerp(DataType begin, DataType end, float t); @@ -38,16 +59,40 @@ namespace Demo.Game }); } + private void BuildupCompiledEntriesAndReleaseEntries() + { + Entries.Sort((x, y) => x.TimePoint.CompareTo(y.TimePoint)); + CompiledEntries = new( + new NativeArray(Entries.Count, Allocator.Persistent), + new NativeArray(Entries.Count, Allocator.Persistent), + new NativeArray(Entries.Count, Allocator.Persistent), + Entries.Count + ); + int index = 0; + foreach (var item in Entries) + { + CompiledEntries.TimePoints[index] = item.TimePoint; + CompiledEntries.Positions[index] = item.Position; + CompiledEntries.EaseCurveTypes[index] = item.easeCurveType; + index++; + } + Entries.Clear(); + Entries = null; + } + private void UpdateEntry(int start, float percent) { - UpdatementEntry head = Entries[start], tail = Entries[Mathf.Min(start + 1, Entries.Count - 1)]; - UpdateData(Lerp(head.Position, tail.Position, MathExtension.Evaluate(Mathf.Clamp01(percent), head.easeCurveType))); + int head = start; + int tail = Mathf.Min(start + 1, CompiledEntries.Count - 1); + UpdateData(Lerp(CompiledEntries.Positions[start], + CompiledEntries.Positions[tail], + MathExtension.Evaluate(Mathf.Clamp01(percent), CompiledEntries.EaseCurveTypes[head]))); } protected override IEnumerator DoSomethingDuringApplyScript() { yield return base.DoSomethingDuringApplyScript(); - Entries.Sort((x, y) => x.TimePoint.CompareTo(y.TimePoint)); + BuildupCompiledEntriesAndReleaseEntries(); if (UpdateTarget == null) { UpdateTarget = Parent.gameObject; @@ -63,7 +108,7 @@ namespace Demo.Game public override IEnumerator UnloadScript() { Content = 0; - Entries.Clear(); + CompiledEntries = default; yield return base.UnloadScript(); } @@ -73,10 +118,10 @@ namespace Demo.Game float GetPercentValue() { - return (currentTime - Entries[Content].TimePoint) / (Entries[Content + 1].TimePoint - Entries[Content].TimePoint); + return (currentTime - CompiledEntries.TimePoints[Content]) / (CompiledEntries.TimePoints[Content + 1] - CompiledEntries.TimePoints[Content]); } - if (Entries.Count <= 1) + if (CompiledEntries.Count <= 1) return; switch (tickType) { @@ -84,19 +129,19 @@ namespace Demo.Game case TickType.Start: { Content = 0; - while (Content + 1 < Entries.Count && Entries[Content + 1].TimePoint < currentTime) + while (Content + 1 < CompiledEntries.Count && CompiledEntries.TimePoints[Content + 1] < currentTime) Content++; UpdateEntry(Content, GetPercentValue()); } break; default: - if (Entries[0].TimePoint > currentTime) + if (CompiledEntries.TimePoints[0] > currentTime) return; - if (Content + 1 >= Entries.Count) + if (Content + 1 >= CompiledEntries.Count) return; - if (Entries[Content + 1].TimePoint < currentTime) + if (CompiledEntries.TimePoints[Content + 1] < currentTime) Content++; - if (Content + 1 >= Entries.Count) + if (Content + 1 >= CompiledEntries.Count) UpdateEntry(Content, 1); else UpdateEntry(Content, GetPercentValue()); @@ -106,21 +151,21 @@ namespace Demo.Game public DataType Evaluate(float time) { - if (Entries.Count == 0) + if (CompiledEntries.Count == 0) return default; - if (Entries.Count == 1) - return Entries[0].Position; - if (time < Entries[0].TimePoint) - return Entries[0].Position; - for (int i = 1; i < Entries.Count; i++) + if (CompiledEntries.Count == 1) + return CompiledEntries.Positions[0]; + if (time < CompiledEntries.TimePoints[0]) + return CompiledEntries.Positions[0]; + for (int i = 1; i < CompiledEntries.Count; i++) { - if (Entries[i - 1].TimePoint <= time && Entries[i].TimePoint > time) + if (CompiledEntries.TimePoints[i - 1] <= time && CompiledEntries.TimePoints[i] > time) { - return Lerp(Entries[i - 1].Position, Entries[i].Position, - (time - Entries[i - 1].TimePoint) / (Entries[i].TimePoint - Entries[i - 1].TimePoint)); + return Lerp(CompiledEntries.Positions[i - 1], CompiledEntries.Positions[i], + (time - CompiledEntries.TimePoints[i - 1]) / (CompiledEntries.TimePoints[i] - CompiledEntries.TimePoints[i - 1])); } } - return Entries[^1].Position; + return CompiledEntries.Positions[^1]; } [Content] public GameObject UpdateTarget; @@ -140,107 +185,10 @@ namespace Demo.Game /// 实例在父类中控制 protected override void SetupTimelineItem(TimelineItem item) { - if (Entries.Count == 0) + if (CompiledEntries.Count == 0) return; - item.SetupDuration(new(Entries[0].TimePoint, Entries[^1].TimePoint), GetTimelineItemColor()); - } - } - - public interface ILocalUpdatement: IScriptableObject - { - int Content { get; set; } - public List> Entries { get; set; } - void UpdateData(DataType data); - DataType Lerp(DataType begin, DataType end, float t); - } - - public static class ILocalUpdatementExtension - { - [Serializable] - public class UpdatementEntry - { - public float TimePoint = 0; - public DataType Position = default; - public MathExtension.EaseCurveType easeCurveType = MathExtension.EaseCurveType.Linear; - } - - public static void AddEntry(this ILocalUpdatement self, float time, DataType position, MathExtension.EaseCurveType curveType) - { - self.Entries.Add(new() - { - TimePoint = time, - Position = position, - easeCurveType = curveType - }); - } - - public static void UpdateEntry(this ILocalUpdatement self, int start, float percent) - { - UpdatementEntry head = self.Entries[start], tail = self.Entries[Mathf.Min(start + 1, self.Entries.Count - 1)]; - self.UpdateData(self.Lerp(head.Position, tail.Position, MathExtension.Evaluate(Mathf.Clamp01(percent), head.easeCurveType))); - } - - public static void LoadScriptHelper(this ILocalUpdatement self) - { - if (self.Entries.Count < 2) - { - self.Entries = new() - { - new() - { - TimePoint=0, - Position=default, - }, - new() - { - TimePoint = float.MaxValue, - Position=default, - } - }; - } - else - { - self.Entries.Sort((x, y) => x.TimePoint.CompareTo(y.TimePoint)); - } - } - - public static void UnloadScriptHelper(this ILocalUpdatement self) - { - self.Content = 0; - self.Entries = new(); - } - public static void UpdateTicks(this ILocalUpdatement self, float currentTime, ScriptableObject.TickType tickType) - { - switch (tickType) - { - case ScriptableObject.TickType.Pause: - //case TickType.LateUpdate: - break; - case ScriptableObject.TickType.Reset: - case ScriptableObject.TickType.Start: - { - self.Content = 0; - while (self.Entries[self.Content + 1].TimePoint < currentTime) - self.Content++; - UpdateEntry(self, self.Content, 0); - } - break; - default: - if (self.Entries[0].TimePoint > currentTime) - return; - if (self.Content + 1 >= self.Entries.Count) - return; - if (self.Entries[self.Content + 1].TimePoint < currentTime) - self.Content++; - if (self.Content + 1 >= self.Entries.Count) - UpdateEntry(self, self.Content, 1); - else - UpdateEntry(self, self.Content, - (currentTime - self.Entries[self.Content].TimePoint) / - (self.Entries[self.Content + 1].TimePoint - self.Entries[self.Content].TimePoint)); - break; - } + item.SetupDuration(new(CompiledEntries.TimePoints[0], CompiledEntries.TimePoints[^1]), GetTimelineItemColor()); } } } diff --git a/Assets/Scripts/LookAtAnchor.cs b/Assets/Scripts/LookAtAnchor.cs index 2c11c1d..d7fa924 100644 --- a/Assets/Scripts/LookAtAnchor.cs +++ b/Assets/Scripts/LookAtAnchor.cs @@ -5,32 +5,36 @@ using UnityEngine; namespace Demo.Game { - public class LookAtAnchor : Updatement + public class LookAtAnchor : Updatement { public static LookAtAnchor Make() { return new GameObject().AddComponent(); } - protected override ScriptableObject Lerp(ScriptableObject begin, ScriptableObject end, float t) + protected override int Lerp(int begin, int end, float t) { return begin; } - [Content] public ScriptableObject LookAtObject; + private readonly List LookAtCache = new(); + + [Content] public int LookAtObject; [Content] public bool IsEnableUpdateEveryTick = false; - protected override void UpdateData(ScriptableObject data) + protected override void UpdateData(int data) { + ScriptableObject target = LookAtCache[LookAtObject]; if (data != LookAtObject) { LookAtObject = data; - transform.LookAt(LookAtObject.transform); + if (target != null) + transform.LookAt(target.transform); } else if (IsEnableUpdateEveryTick) { - if (LookAtObject != null) - transform.LookAt(LookAtObject.transform); + if (target != null) + transform.LookAt(target.transform); } } @@ -40,7 +44,8 @@ namespace Demo.Game [Convention.RScript.Variable.Attr.Method] public void Add(float time, ScriptableObject target) { - ManualAddEntry(time, target, default); + LookAtCache.Add(target); + ManualAddEntry(time, LookAtCache.Count - 1, default); } /// diff --git a/Assets/Scripts/MaterialUpdatement.cs b/Assets/Scripts/MaterialUpdatement.cs index e7d2c29..3caa886 100644 --- a/Assets/Scripts/MaterialUpdatement.cs +++ b/Assets/Scripts/MaterialUpdatement.cs @@ -1,41 +1,47 @@ +using Convention; using System.Collections; using System.Collections.Generic; -using Convention; using UnityEngine; +using UnityEngine.Rendering.LookDev; namespace Demo.Game { - public class MaterialUpdatement : Updatement, IAssetBundleLoader + public class MaterialUpdatement : Updatement, IAssetBundleLoader { public static MaterialUpdatement Make() { return new GameObject().AddComponent(); } + private readonly Dictionary NameCache = new(); + private readonly Dictionary MaterialCache = new(); + public string MaterialAssetBundlePath = null; public AssetBundle MaterialAssetBundle = null; - protected override Material Lerp(Material begin, Material end, float t) + protected override int Lerp(int begin, int end, float t) { return begin; } - [Content, SerializeField] private Material Cache; + [Content, SerializeField] private int Cache; - protected override void UpdateData(Material data) + protected override void UpdateData(int data) { if (string.IsNullOrEmpty(MaterialAssetBundlePath)) return; + if (Cache < 0) + return; if (Cache != data && Parent.TryGetComponent(out var meshRenderer)) { - meshRenderer.material = data; + meshRenderer.material = MaterialCache[data]; Cache = data; } } public override IEnumerator UnloadScript() { - Cache = null; + Cache = -1; if (string.IsNullOrEmpty(MaterialAssetBundlePath) == false) yield return this.UnloadAssetBundle(MaterialAssetBundlePath); MaterialAssetBundlePath = null; @@ -66,7 +72,13 @@ namespace Demo.Game ir.completed += x => { var mat = ir.asset as Material; - ManualAddEntry(time, mat, default); + if (NameCache.TryGetValue(material, out int id) == false) + { + id = NameCache.Count; + NameCache[material] = id; + } + MaterialCache[id] = mat; + ManualAddEntry(time, id, default); }; yield return ir; }