using System; using System.Collections.Generic; using Dreamteck.Splines; using UnityEngine; namespace Ichni.RhythmGame { public partial class ObjectTracker : GameElement { #region [运行时缓存数据] Property Caches public Track track; public ObjectController objectController; public GameObject objectPrefab; private List themeBundleList; private List objectNameList; public string themeBundleName; public string objectName; public float playTime; public float stopTime; public int spawnCount; public Vector2 positionOffsetMin = Vector2.zero; public Vector2 positionOffsetMax = Vector2.zero; public string customPositionRuleName; public bool applyRotationOffset = false; public Vector3 rotationOffsetMin = Vector3.zero; public Vector3 rotationOffsetMax = Vector3.zero; public string customRotationRuleName; public bool applyScaleOffset = false; public Vector3 scaleOffsetMin = Vector3.one; public Vector3 scaleOffsetMax = Vector3.one; public string customScaleRuleName; #endregion #region [生成与初始化] Generation & Initialization public static ObjectTracker GenerateElement(string elementName, Guid id, List tags, bool isFirstGenerated, Track track, string themeBundleName, string objectName, int spawnCount, Vector2 positionOffsetMin, Vector2 positionOffsetMax, string customPositionRuleName, bool applyRotationOffset, Vector3 rotationOffsetMin, Vector3 rotationOffsetMax, string customRotationRuleName, bool applyScaleOffset, Vector3 scaleOffsetMin, Vector3 scaleOffsetMax, string customScaleRuleName) { ObjectTracker objectTracker = Instantiate(GameManager.Instance.basePrefabs.objectTracker, track.transform) .GetComponent(); objectTracker.objectPrefab = ThemeBundleManager.instance.GetObject(themeBundleName, objectName); objectTracker.objectController.objects = new[] { objectTracker.objectPrefab }; objectTracker.Initialize(elementName, id, tags, isFirstGenerated, track); objectTracker.track = track; objectTracker.objectController.spline = track.trackPathSubmodule.path; objectTracker.themeBundleList = ThemeBundleManager.instance.loadedThemeBundleList.ConvertAll(x => x.themeBundleName); objectTracker.objectNameList = new List(); objectTracker.themeBundleName = themeBundleName; objectTracker.objectName = objectName; objectTracker.SetSpawnSettings(spawnCount, positionOffsetMin, positionOffsetMax, customPositionRuleName, applyRotationOffset, rotationOffsetMin, rotationOffsetMax, customRotationRuleName, applyScaleOffset, scaleOffsetMin, scaleOffsetMax, customScaleRuleName); if (isFirstGenerated) objectTracker.AfterInitialize(); return objectTracker; } public override void AfterInitialize() { base.AfterInitialize(); // 向 ElementUpdateScheduler 注册 Phase.TrackFollower CoreServices.UpdateScheduler.Register(UpdatePhase.TrackFollower, this); } public void SetSpawnSettings(int spawnCount, Vector2 positionOffsetMin, Vector2 positionOffsetMax, string customPositionRuleName, bool applyRotationOffset, Vector3 rotationOffsetMin, Vector3 rotationOffsetMax, string customRotationRuleName, bool applyScaleOffset, Vector3 scaleOffsetMin, Vector3 scaleOffsetMax, string customScaleRuleName) { this.spawnCount = spawnCount; this.positionOffsetMin = positionOffsetMin; this.positionOffsetMax = positionOffsetMax; this.customPositionRuleName = customPositionRuleName; this.applyRotationOffset = applyRotationOffset; this.rotationOffsetMin = rotationOffsetMin; this.rotationOffsetMax = rotationOffsetMax; this.customRotationRuleName = customRotationRuleName; this.applyScaleOffset = applyScaleOffset; this.scaleOffsetMin = scaleOffsetMin; this.scaleOffsetMax = scaleOffsetMax; this.customScaleRuleName = customScaleRuleName; objectController.spawnCount = spawnCount; objectController.minOffset = positionOffsetMin; objectController.maxOffset = positionOffsetMax; objectController.applyRotation = applyRotationOffset; objectController.minRotation = rotationOffsetMin; objectController.maxRotation = rotationOffsetMax; objectController.applyScale = applyScaleOffset; objectController.minScaleMultiplier = scaleOffsetMin; objectController.maxScaleMultiplier = scaleOffsetMax; objectController.Spawn(); } #endregion #region [运行时控制] Update /// /// IScheduledElement 实现:在 Phase.TrackFollower 阶段控制 objectController 的启用/禁用。 /// public override void ScheduledUpdate(UpdatePhase phase, float songTime) { if (phase == UpdatePhase.TrackFollower) { if (playTime > songTime || stopTime < songTime) { if (objectController.enabled) objectController.enabled = false; } else { if (!objectController.enabled) { objectController.enabled = true; objectController.Spawn(); } } } } public override void OnDelete() { CoreServices.UpdateScheduler.Unregister(UpdatePhase.TrackFollower, this); } #endregion } }