274 lines
6.8 KiB
C#
274 lines
6.8 KiB
C#
using UnityEngine;
|
|
using System.Collections.Generic;
|
|
using DG.Tweening;
|
|
using System;
|
|
|
|
public class ModelController : MonoBehaviour
|
|
{
|
|
private Animator animator;
|
|
private string currentAnim = "";
|
|
private bool isPlaying = false;
|
|
private Vector3 originalPosition;
|
|
private Vector3 originalScale;
|
|
|
|
[SerializeField] private string defaultAnimName = "Take 001";
|
|
[SerializeField] private bool hasAnimation = true;
|
|
|
|
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>();
|
|
originalPosition = transform.localPosition;
|
|
originalScale = transform.localScale;
|
|
|
|
if (hasAnimation)
|
|
{
|
|
if (animator == null)
|
|
{
|
|
hasAnimation = false;
|
|
}
|
|
else
|
|
{
|
|
CacheAnimationStates();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (animator != null)
|
|
{
|
|
animator.enabled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CacheAnimationStates()
|
|
{
|
|
if (!hasAnimation) return;
|
|
|
|
stateHashes.Clear();
|
|
if (!string.IsNullOrEmpty(defaultAnimName))
|
|
{
|
|
stateHashes[defaultAnimName] = Animator.StringToHash(defaultAnimName);
|
|
}
|
|
if (animator.runtimeAnimatorController != null)
|
|
{
|
|
foreach (var clip in animator.runtimeAnimatorController.animationClips)
|
|
{
|
|
if (!stateHashes.ContainsKey(clip.name))
|
|
{
|
|
stateHashes[clip.name] = Animator.StringToHash(clip.name);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hasAnimation = false;
|
|
animator.enabled = false;
|
|
}
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (!hasAnimation || !isPlaying || animator == null || string.IsNullOrEmpty(currentAnim)) return;
|
|
|
|
if (!animator.enabled)
|
|
{
|
|
animator.enabled = true;
|
|
}
|
|
transform.localScale = originalScale;
|
|
transform.localPosition = originalPosition;
|
|
AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo(0);
|
|
if (stateInfo.IsName(currentAnim) && stateInfo.normalizedTime >= 1f && !animator.IsInTransition(0))
|
|
{
|
|
isPlaying = false;
|
|
animator.enabled = false;
|
|
transform.localScale = originalScale;
|
|
transform.localPosition = originalPosition;
|
|
OnAnimationFinished?.Invoke();
|
|
}
|
|
}
|
|
|
|
public void PlayAnimation()
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (animator == null || string.IsNullOrEmpty(defaultAnimName) || !gameObject.activeSelf)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!AnimatorHasState(defaultAnimName))
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentAnim = defaultAnimName;
|
|
animator.enabled = true;
|
|
animator.Play(stateHashes[currentAnim], 0, 0f);
|
|
animator.Update(0f);
|
|
isPlaying = true;
|
|
transform.localScale = originalScale;
|
|
transform.localPosition = originalPosition;
|
|
}
|
|
|
|
public void SetAnimationProgress(float normalizedTime)
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (animator == null || string.IsNullOrEmpty(defaultAnimName) || !gameObject.activeSelf)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(currentAnim))
|
|
{
|
|
currentAnim = defaultAnimName;
|
|
}
|
|
|
|
if (!AnimatorHasState(currentAnim))
|
|
{
|
|
return;
|
|
}
|
|
|
|
isPlaying = false;
|
|
animator.enabled = true;
|
|
float clampedTime = Mathf.Clamp01(normalizedTime);
|
|
animator.Play(stateHashes[currentAnim], 0, clampedTime);
|
|
animator.Update(0f);
|
|
animator.enabled = false;
|
|
transform.localScale = originalScale;
|
|
transform.localPosition = originalPosition;
|
|
}
|
|
|
|
public void ResetAnimation()
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (animator == null || !gameObject.activeSelf)
|
|
{
|
|
return;
|
|
}
|
|
|
|
string animToReset = !string.IsNullOrEmpty(defaultAnimName) ? defaultAnimName : "";
|
|
if (string.IsNullOrEmpty(animToReset))
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!AnimatorHasState(animToReset))
|
|
{
|
|
return;
|
|
}
|
|
|
|
currentAnim = animToReset;
|
|
animator.enabled = true;
|
|
animator.Play(stateHashes[currentAnim], 0, 0f);
|
|
animator.Update(0f);
|
|
animator.enabled = false;
|
|
isPlaying = false;
|
|
transform.localScale = originalScale;
|
|
transform.localPosition = originalPosition;
|
|
}
|
|
|
|
public void MoveModel(float xOffset)
|
|
{
|
|
if (!gameObject.activeSelf)
|
|
{
|
|
return;
|
|
}
|
|
Vector3 targetPosition = originalPosition + new Vector3(xOffset, 0f, 0f);
|
|
transform.DOLocalMoveX(targetPosition.x, 1f).SetEase(Ease.InOutSine).OnComplete(() =>
|
|
{
|
|
transform.localScale = originalScale;
|
|
});
|
|
}
|
|
|
|
public void ResetModelPosition()
|
|
{
|
|
if (!gameObject.activeSelf)
|
|
{
|
|
return;
|
|
}
|
|
transform.DOLocalMoveX(originalPosition.x, 1f).SetEase(Ease.InOutSine).OnComplete(() =>
|
|
{
|
|
transform.localScale = originalScale;
|
|
});
|
|
}
|
|
|
|
public float GetAnimationProgress()
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return 0f;
|
|
}
|
|
|
|
if (animator == null || !animator.enabled || 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);
|
|
return progress;
|
|
}
|
|
return 0f;
|
|
}
|
|
|
|
private bool AnimatorHasState(string stateName)
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(stateName) || !stateHashes.TryGetValue(stateName, out int hash))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < animator.layerCount; i++)
|
|
{
|
|
if (animator.HasState(i, hash))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public bool IsPlayingAnimation()
|
|
{
|
|
if (!hasAnimation)
|
|
{
|
|
return false;
|
|
}
|
|
return isPlaying;
|
|
}
|
|
|
|
public bool GetHasAnimation()
|
|
{
|
|
return hasAnimation;
|
|
}
|
|
} |