AnimalSimulation/Assets/Scripts/ModelController.cs

150 lines
4.6 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;
public class ModelController : MonoBehaviour
{
private Animator animator; // 控制动画的Animator组件
private string currentAnim = ""; // 跟踪当前播放的动画
private bool isPlaying = false; // 跟踪动画播放状态
[Header("默认动画状态名称")]
public string defaultAnimName = "Idle"; // 默认动画状态名称
private Dictionary<string, int> stateHashes = new Dictionary<string, int>(); // 动画状态哈希缓存
// 脚本初始化时调用
void Awake()
{
animator = GetComponent<Animator>();
// 缓存默认动画状态的哈希值以提高性能
if (!string.IsNullOrEmpty(defaultAnimName))
{
stateHashes[defaultAnimName] = Animator.StringToHash(defaultAnimName);
}
}
// 在Update中更新动画状态
void Update()
{
if (isPlaying && animator != null && !string.IsNullOrEmpty(currentAnim))
{
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName(currentAnim) && stateInfo.normalizedTime >= 1f)
{
// 动画播放完成,暂停并标记
animator.enabled = false;
isPlaying = false;
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;
}
animator.enabled = true;
float clampedTime = Mathf.Clamp01(normalizedTime);
animator.Play(currentAnim, 0, clampedTime); // 设置动画到指定时间
animator.Update(0f); // 强制立即更新
animator.enabled = false; // 暂停动画
isPlaying = 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 || string.IsNullOrEmpty(currentAnim) || !gameObject.activeSelf)
{
return 0f;
}
if (!AnimatorHasState(currentAnim))
{
return 0f;
}
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
if (stateInfo.IsName(currentAnim))
{
float progress = Mathf.Clamp01(stateInfo.normalizedTime % 1f);
Debug.Log($"获取动画 {currentAnim} 进度: {progress:F2}");
return progress;
}
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;
}
}