NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/FlipbookAnimationStarter.cs

128 lines
3.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using UnityEngine;
/// <summary>
/// Flipbook动画启动器
/// 用于非循环的Flipbook动画在对象激活时自动设置_StartTime使动画从当前时间开始播放
/// </summary>
public class FlipbookAnimationStarter : MonoBehaviour
{
[Header("设置")]
[Tooltip("是否在OnEnable时自动设置StartTime")]
public bool autoSetOnEnable = true;
[Tooltip("使用Material实例还是共享Material建议使用实例")]
public bool useMaterialInstance = true;
[Tooltip("是否也处理子对象的Renderer")]
public bool includeChildren = false;
private static readonly int StartTimePropertyID = Shader.PropertyToID("_StartTime");
private MaterialPropertyBlock _propertyBlock;
private Renderer[] _renderers;
private void Awake()
{
// 初始化MaterialPropertyBlock性能更好的方式
_propertyBlock = new MaterialPropertyBlock();
// 获取所有Renderer
if (includeChildren)
{
_renderers = GetComponentsInChildren<Renderer>(true);
}
else
{
var renderer = GetComponent<Renderer>();
_renderers = renderer != null ? new[] { renderer } : new Renderer[0];
}
}
private void OnEnable()
{
if (autoSetOnEnable)
{
SetStartTime();
}
}
/// <summary>
/// 手动设置动画开始时间
/// </summary>
public void SetStartTime()
{
SetStartTime(Time.time);
}
/// <summary>
/// 设置指定的开始时间
/// </summary>
public void SetStartTime(float startTime)
{
foreach (var renderer in _renderers)
{
if (renderer == null) continue;
if (useMaterialInstance)
{
// 方式1: 使用MaterialPropertyBlock推荐不会创建材质实例性能更好
renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetFloat(StartTimePropertyID, startTime);
renderer.SetPropertyBlock(_propertyBlock);
}
else
{
// 方式2: 使用Material实例会创建材质副本
// 注意renderer.material会自动创建材质实例
renderer.material.SetFloat(StartTimePropertyID, startTime);
}
}
}
/// <summary>
/// 重置动画到第一帧
/// </summary>
public void ResetAnimation()
{
SetStartTime(0f);
}
/// <summary>
/// 从当前时间重新播放动画
/// </summary>
public void RestartAnimation()
{
SetStartTime(Time.time);
}
#if UNITY_EDITOR
[ContextMenu("设置StartTime为当前时间")]
private void EditorSetStartTime()
{
if (Application.isPlaying)
{
SetStartTime();
Debug.Log($"已设置 {gameObject.name} 的StartTime为 {Time.time}");
}
else
{
Debug.LogWarning("请在运行时执行此操作");
}
}
[ContextMenu("重置StartTime为0")]
private void EditorResetStartTime()
{
if (Application.isPlaying)
{
ResetAnimation();
Debug.Log($"已重置 {gameObject.name} 的StartTime为0");
}
else
{
Debug.LogWarning("请在运行时执行此操作");
}
}
#endif
}