Files
ichni_Official/Assets/Scripts/Game/Animations/Transform/LookAt.cs
SoulliesOfficial 7c60c40d6b 同步
2026-06-05 04:45:57 -04:00

120 lines
4.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections;
using System.Collections.Generic;
using Ichni.RhythmGame.Beatmap;
using UniRx;
using UnityEngine;
namespace Ichni.RhythmGame
{
/// <summary>
/// 将物体的z轴指向目标物体注意LookAt的启用期间物体的旋转将被锁定
/// </summary>
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<string> tags, bool isFirstGenerated, GameElement animatedObject,
GameElement lookAtTarget, FlexibleBool enabling)
{
LookAt look = Instantiate(GameManager.Instance.basePrefabs.emptyObject).AddComponent<LookAt>();
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();
// 注册 Phase 7Effect确保在 Track/TrackFollowerPhase 4/5和 NotePhase 6
// 全部更新完毕后再计算旋转覆盖,避免因位置尚未就绪导致的旋转抖动
CoreServices.UpdateScheduler.Register(UpdatePhase.Effect, this);
}
public override void OnDelete()
{
base.OnDelete();
CoreServices.UpdateScheduler.Unregister(UpdatePhase.Effect, this);
}
public override void ManualUpdate(float songTime, bool forceUpdate = false)
{
base.ManualUpdate(songTime, forceUpdate);
// 动画结束时同步注销 Phase 7
if (timeDurationSubmodule.CheckAfterEndTime(songTime))
{
CoreServices.UpdateScheduler.Unregister(UpdatePhase.Effect, this);
}
}
#endregion
#region [] Core Animation Logic
public override void ScheduledUpdate(UpdatePhase phase, float songTime)
{
switch (phase)
{
case UpdatePhase.Animation:
base.ScheduledUpdate(phase, songTime);
break;
case UpdatePhase.Effect:
// 在所有 Track/TrackFollower/Note 位置更新完毕后覆盖旋转
if (enabling.value)
{
(animatedObject as IHaveTransformSubmodule)?.UpdateLookAt(this);
}
break;
}
}
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
}
}