190 lines
6.2 KiB
C#
190 lines
6.2 KiB
C#
using UnityEngine;
|
||
using System.Collections.Generic;
|
||
using System;
|
||
|
||
public class ModelController : MonoBehaviour
|
||
{
|
||
private Animator animator; // 控制动画的Animator组件
|
||
private string currentAnim = ""; // 跟踪当前播放的动画
|
||
private bool isPlaying = false; // 跟踪动画播放状态
|
||
|
||
[Header("默认动画状态名称")]
|
||
public string defaultAnimName = "Take 001"; // 默认动画状态名称
|
||
|
||
private Dictionary<string, int> stateHashes = new Dictionary<string, int>(); // 动画状态哈希缓存
|
||
private float lastLoggedProgress = -1f; // 记录上次日志的进度值
|
||
private float lastWarningTime = 0f; // 记录上次警告日志时间
|
||
private const float warningInterval = 1f; // 警告日志间隔(秒)
|
||
|
||
// 动画结束事件
|
||
public event Action OnAnimationFinished;
|
||
|
||
// 脚本初始化时调用
|
||
void Awake()
|
||
{
|
||
animator = GetComponent<Animator>();
|
||
// 缓存默认动画状态的哈希值以提高性能
|
||
if (!string.IsNullOrEmpty(defaultAnimName))
|
||
{
|
||
stateHashes[defaultAnimName] = Animator.StringToHash(defaultAnimName);
|
||
}
|
||
}
|
||
|
||
// 在Update中更新动画状态
|
||
void Update()
|
||
{
|
||
if (isPlaying && animator != null && !string.IsNullOrEmpty(currentAnim))
|
||
{
|
||
if (!animator.enabled)
|
||
{
|
||
animator.enabled = true; // 确保Animator启用
|
||
Debug.Log($"重新启用Animator: {currentAnim}");
|
||
}
|
||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||
if (stateInfo.IsName(currentAnim) && stateInfo.normalizedTime >= 1f)
|
||
{
|
||
// 动画播放完成,暂停并标记
|
||
animator.enabled = false;
|
||
isPlaying = false;
|
||
OnAnimationFinished?.Invoke(); // 通知动画结束
|
||
Debug.Log($"动画 {currentAnim} 播放完成,暂停");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 从头播放默认动画
|
||
/// </summary>
|
||
public void PlayAnimation()
|
||
{
|
||
if (animator == null || string.IsNullOrEmpty(defaultAnimName)) return;
|
||
if (!AnimatorHasState(defaultAnimName))
|
||
{
|
||
Debug.LogWarning($"Animator上不存在状态: {defaultAnimName}");
|
||
return;
|
||
}
|
||
|
||
currentAnim = defaultAnimName;
|
||
animator.enabled = true;
|
||
animator.Play(currentAnim, 0, 0f); // 从头播放动画
|
||
animator.Update(0f); // 强制立即更新
|
||
isPlaying = true; // 标记动画正在播放
|
||
Debug.Log($"开始播放动画: {currentAnim}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置动画进度(0到1)
|
||
/// </summary>
|
||
public void SetAnimationProgress(float normalizedTime)
|
||
{
|
||
if (animator == null || string.IsNullOrEmpty(defaultAnimName)) return;
|
||
if (!gameObject.activeSelf) return;
|
||
|
||
// 确保currentAnim已设置
|
||
if (string.IsNullOrEmpty(currentAnim))
|
||
{
|
||
currentAnim = defaultAnimName;
|
||
Debug.Log($"设置动画进度前初始化currentAnim: {currentAnim}");
|
||
}
|
||
|
||
if (!AnimatorHasState(currentAnim))
|
||
{
|
||
Debug.LogWarning($"Animator上不存在状态: {currentAnim}");
|
||
return;
|
||
}
|
||
|
||
// 停止播放状态
|
||
isPlaying = false;
|
||
animator.enabled = true;
|
||
float clampedTime = Mathf.Clamp01(normalizedTime);
|
||
animator.Play(currentAnim, 0, clampedTime); // 设置动画到指定时间
|
||
animator.Update(0f); // 强制立即更新
|
||
animator.enabled = false; // 暂停动画
|
||
Debug.Log($"设置动画 {currentAnim} 进度: {clampedTime:F2}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置动画到初始状态
|
||
/// </summary>
|
||
public void ResetAnimation()
|
||
{
|
||
if (animator == null) return;
|
||
if (!gameObject.activeSelf) return;
|
||
|
||
string animToReset = !string.IsNullOrEmpty(defaultAnimName) ? defaultAnimName : "";
|
||
if (string.IsNullOrEmpty(animToReset)) return;
|
||
|
||
currentAnim = animToReset; // 确保currentAnim已设置
|
||
animator.enabled = true;
|
||
animator.Play(currentAnim, 0, 0f); // 重置到开始
|
||
animator.Update(0f); // 强制立即更新
|
||
animator.enabled = false; // 暂停动画
|
||
isPlaying = false; // 标记动画暂停
|
||
Debug.Log($"重置动画: {currentAnim}");
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前动画的标准化时间(0到1)
|
||
/// </summary>
|
||
/// <returns>当前动画进度,若无动画则返回0</returns>
|
||
public float GetAnimationProgress()
|
||
{
|
||
if (animator == null || !animator.enabled || string.IsNullOrEmpty(currentAnim) || !gameObject.activeSelf)
|
||
{
|
||
if (Time.time - lastWarningTime >= warningInterval)
|
||
{
|
||
Debug.LogWarning($"无法获取动画进度: animator={animator}, enabled={animator?.enabled}, currentAnim={currentAnim}, active={gameObject.activeSelf}");
|
||
lastWarningTime = Time.time;
|
||
}
|
||
return 0f;
|
||
}
|
||
|
||
if (!AnimatorHasState(currentAnim))
|
||
{
|
||
if (Time.time - lastWarningTime >= warningInterval)
|
||
{
|
||
Debug.LogWarning($"Animator上不存在状态: {currentAnim}");
|
||
lastWarningTime = Time.time;
|
||
}
|
||
return 0f;
|
||
}
|
||
|
||
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
||
if (stateInfo.IsName(currentAnim))
|
||
{
|
||
float progress = Mathf.Clamp01(stateInfo.normalizedTime % 1f);
|
||
// 仅当进度变化超过0.01时记录日志
|
||
if (Mathf.Abs(progress - lastLoggedProgress) > 0.01f)
|
||
{
|
||
Debug.Log($"获取动画 {currentAnim} 进度: {progress:F2}");
|
||
lastLoggedProgress = progress;
|
||
}
|
||
return progress;
|
||
}
|
||
if (Time.time - lastWarningTime >= warningInterval)
|
||
{
|
||
Debug.LogWarning($"动画状态不匹配: currentAnim={currentAnim}, state={stateInfo.fullPathHash}");
|
||
lastWarningTime = Time.time;
|
||
}
|
||
return 0f;
|
||
}
|
||
|
||
// 检查指定的动画状态是否存在于Animator中
|
||
private bool AnimatorHasState(string stateName)
|
||
{
|
||
if (stateHashes.TryGetValue(stateName, out int hash))
|
||
{
|
||
for (int i = 0; i < animator.layerCount; i++)
|
||
{
|
||
if (animator.HasState(i, hash)) return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// 获取动画播放状态
|
||
public bool IsPlayingAnimation()
|
||
{
|
||
return isPlaying;
|
||
}
|
||
} |