AnimalSimulation/Assets/Scripts/ModelController.cs

190 lines
6.2 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 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;
}
}