using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Sirenix.OdinInspector; using UniRx; using UnityEngine; namespace Ichni.RhythmGame { [System.Serializable] public abstract partial class BaseElement : SerializedMonoBehaviour { //物体名 public string elementName; //序列号 public int serialNumber; //标识 GUID public Guid elementGuid; //存档 //public BaseElement_BM matchedBM; //父游戏物体 public BaseElement parentElement; //子物体列表 public List childElementList = new List(); //次级模块 public TimeDurationSubmodule timeDurationSubmodule; public TransformSubmodule transformSubmodule; public ColorSubmodule colorSubmodule; /// /// 首次初始化 /// /// 物体名 public virtual void NewInitialize(string name) { this.elementName = name; this.elementGuid = Guid.NewGuid(); //GameManager.beatMapContainer.beatMapElementList.Add(this); //serialNumber = totalSerialNumber++; SetTransformObserver(); } /// /// 在所有物体生成完毕后,执行的初始化方法 /// public virtual void AfterInitialize() { } /// /// 刷新物体的状态 /// public virtual void Refresh() { } /// /// 设置父物体 /// /// 父物体 public void SetParent(BaseElement parentElement) { if (parentElement != null) { parentElement.childElementList.Add(this); this.parentElement = parentElement; transform.SetParent(parentElement.transform); } } } public abstract partial class BaseElement { private void Start() { SetTransformObserver(); } public virtual void SetTimeDuration() { } [Button("Apply Time Duration From Child")] public void ApplyTimeDuration() { childElementList.ForEach(x => x.ApplyTimeDuration()); timeDurationSubmodule?.SetDurationFromChildren(childElementList.Select(x=>x.timeDurationSubmodule).ToList()); } /// /// 设置物体Transform的监听,顺序为Scale -> EulerAngles -> Position /// 如果有一些特殊的物体(例如Camera,ElementFolder),需要自定义监听,可以重写这个方法 /// public virtual void SetTransformObserver() { Observable.EveryUpdate().Subscribe(_ => { if (transformSubmodule == null) { return; } if (transformSubmodule.scaleDirtyMark) { Vector3 offset = Vector3.zero; foreach (Vector3 scaleOffset in transformSubmodule.scaleOffset) { offset += scaleOffset; } transformSubmodule.currentScale = transformSubmodule.originalScale + offset; transform.localScale = transformSubmodule.currentScale; transformSubmodule.scaleDirtyMark = false; } if (transformSubmodule.eulerAnglesDirtyMark) { Vector3 offset = Vector3.zero; foreach (Vector3 eulerOffset in transformSubmodule.eulerAnglesOffset) { offset += eulerOffset; } transformSubmodule.currentEulerAngles = transformSubmodule.originalEulerAngles + offset; transform.localEulerAngles = transformSubmodule.currentEulerAngles; transformSubmodule.eulerAnglesDirtyMark = false; } if (transformSubmodule.positionDirtyMark) { Vector3 offset = Vector3.zero; foreach (Vector3 posOffset in transformSubmodule.positionOffset) { offset += posOffset; } transformSubmodule.currentPosition = transformSubmodule.originalPosition + offset; transform.localPosition = transformSubmodule.currentPosition; transformSubmodule.positionDirtyMark = false; } transformSubmodule.scaleOffset.Clear(); transformSubmodule.eulerAnglesOffset.Clear(); transformSubmodule.positionOffset.Clear(); }).AddTo(gameObject); } } }