using System; using System.Collections; using System.Collections.Generic; using Ichni.RhythmGame.Beatmap; using UniRx; using UnityEngine; namespace Ichni.RhythmGame { /// /// 将物体的z轴指向目标物体,注意,LookAt的启用期间,物体的旋转将被锁定 /// public partial class LookAt : AnimationBase { #region [暴露属性字段与关联] Exposed Fields & References public GameElement targetGameElement; public TransformSubmodule targetTransformSubmodule; public FlexibleBool enabling; #endregion #region [生命周期与工厂] Lifecycle & Factory public static LookAt GenerateElement(string elementName, Guid id, List tags, bool isFirstGenerated, GameElement animatedObject, GameElement lookAtTarget, FlexibleBool enabling) { LookAt look = Instantiate(GameManager.Instance.basePrefabs.emptyObject).AddComponent(); look.Initialize(elementName, id, tags, isFirstGenerated, animatedObject); look.animatedObject = animatedObject; look.enabling = enabling; look.animationReturnType = FlexibleReturnType.Before; look.targetGameElement = lookAtTarget; look.targetTransformSubmodule = (animatedObject as IHaveTransformSubmodule).transformSubmodule; //look.timeDurationSubmodule.SetDuration(-999f, 999f); //TODO: 换为(-delay, songLength) return look; } public override void SetDefaultSubmodules() { timeDurationSubmodule = new TimeDurationSubmodule(this); } public override void AfterInitialize() { base.AfterInitialize(); } #endregion #region [核心动画逻辑] Core Animation Logic void LateUpdate() { if (enabling.value) { (animatedObject as IHaveTransformSubmodule)?.UpdateLookAt(this); } } protected override void UpdateAnimation(float songTime, bool forceUpdate) { if (targetGameElement is null) return; enabling.UpdateFlexibleBool(songTime); if (!targetTransformSubmodule.eulerAnglesOffsetLock || enabling.value) { targetTransformSubmodule.eulerAnglesOffsetLock = enabling.value; } if (enabling.value) { animationReturnType = FlexibleReturnType.MiddleExecuting; targetTransformSubmodule.eulerAnglesDirtyMark = true; } else if (animationReturnType != FlexibleReturnType.MiddleInterval) { animationReturnType = FlexibleReturnType.MiddleInterval; targetTransformSubmodule.eulerAnglesDirtyMark = true; } } public override void ApplyTimeOffset(float offset) { base.ApplyTimeOffset(offset); enabling.animations.ForEach(anim => anim.ApplyTimeOffset(offset)); } #endregion } }