feat(scene-mgmt): 添加随机动画播放系统和 Yarn 指令

This commit is contained in:
2026-04-21 14:10:44 +08:00
parent 5cbc46ce73
commit 487ee0a991
5 changed files with 166 additions and 0 deletions
@@ -9,6 +9,7 @@ namespace AibisDream
public class AnimatorCenter : SingletonBase<AnimatorCenter>
{
private readonly Dictionary<string, AnimatorHandler> _handlers = new();
private readonly Dictionary<string, RandomAnimatorHandler> _randomHandlers = new();
private AnimatorCenter() { }
@@ -22,6 +23,42 @@ namespace AibisDream
_handlers.Remove(handler.animatorName);
}
public void RegisterRandomHandler(RandomAnimatorHandler handler)
{
_randomHandlers.Add(handler.handelrName, handler);
}
public void UnregisterRandomHandler(RandomAnimatorHandler handler)
{
_randomHandlers.Remove(handler.handelrName);
}
public void StartRandomAnimation(string handlerName)
{
if (!TryGetRandomHandler(handlerName, out RandomAnimatorHandler randomHandler))
return;
randomHandler.StartRandomPlay();
}
public void StopRandomAnimation(string handlerName)
{
if (!TryGetRandomHandler(handlerName, out RandomAnimatorHandler randomHandler))
return;
randomHandler.StopRandomPlay();
}
private bool TryGetRandomHandler(string handlerName, out RandomAnimatorHandler handler)
{
if (_randomHandlers.TryGetValue(handlerName, out handler))
return true;
Debug.LogError($"AnimatorCenter: 未找到名为 \"{handlerName}\" 的 RandomAnimatorHandler。");
handler = null;
return false;
}
private bool TryGetHandler(string animatorName, out AnimatorHandler handler)
{
if (_handlers.TryGetValue(animatorName, out handler))
@@ -102,6 +139,14 @@ namespace AibisDream
animatorHandler.Reset();
}
public void ReturnToDefaultState(string animatorName)
{
if (!TryGetHandler(animatorName, out AnimatorHandler animatorHandler))
return;
animatorHandler.ReturnToDefaultState();
}
public void HideAnimation(string animatorName)
{
if (!TryGetHandler(animatorName, out AnimatorHandler animatorHandler))
@@ -347,6 +347,24 @@ namespace AibisDream
ReleaseAddressableHandle();
}
/// <summary>
/// 将 Animator 状态机恢复到当前 <see cref="RuntimeAnimatorController"/> 的默认入口状态(参数与层会按控制器重置),
/// 不释放 Addressable、不还原已替换的运行时控制器。用于在保留当前加载的控制器前提下清掉过渡与参数。
/// </summary>
public void ReturnToDefaultState()
{
if (!EnsureAnimator())
return;
CancelCompletionCoroutine();
_onCompleteCallback = null;
EnsurePlayingSpeedForNewClip();
animator.Rebind();
animator.Update(0f);
}
/// <summary>
/// 当前层当前状态下,已播放时长(秒)。过渡或非目标状态时语义以当前 StateInfo 为准。
/// </summary>
@@ -30,5 +30,17 @@ namespace AibisDream
{
AnimatorCenter.Instance.HideAnimation(animatorName);
}
[YarnCommand("start_random_animation")]
public static void StartRandomAnimation(string handlerName)
{
AnimatorCenter.Instance.StartRandomAnimation(handlerName);
}
[YarnCommand("stop_random_animation")]
public static void StopRandomAnimation(string handlerName)
{
AnimatorCenter.Instance.StopRandomAnimation(handlerName);
}
}
}
@@ -0,0 +1,80 @@
using UnityEngine;
namespace AibisDream
{
public class RandomAnimatorHandler : MonoBehaviour
{
[SerializeField] private Animator targetAnimator;
public string handelrName;
[SerializeField] private Vector2 randomDurationRange;
[SerializeField] private int randomCount;
[SerializeField] private bool playOnAwake;
private bool _isPlaying;
private float _curduration;
private void Awake()
{
if (playOnAwake)
{
StartRandomPlay();
}
}
private void OnEnable()
{
AnimatorCenter.Instance.RegisterRandomHandler(this);
}
private void OnDisable()
{
AnimatorCenter.Instance.UnregisterRandomHandler(this);
}
private void Update()
{
if (_isPlaying)
{
_curduration -= Time.deltaTime;
if (_curduration <= 0)
{
RandomPlay();
_curduration = RandomDuration();
}
}
}
private void RandomPlay()
{
targetAnimator.ResetTrigger("RandomPlay");
// 设置参数
var index = RandomIndex();
targetAnimator.SetInteger("RandomIndex", index);
// 播放
targetAnimator.SetTrigger("RandomPlay");
}
public void StartRandomPlay()
{
_isPlaying = true;
_curduration = RandomDuration();
}
public void StopRandomPlay()
{
_isPlaying = false;
}
private float RandomDuration()
{
return Random.Range(randomDurationRange.x, randomDurationRange.y);
}
private int RandomIndex()
{
return Random.Range(0, randomCount);
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d2070ae592dcf94a98db28bc06281c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: