using UnityEngine;
///
/// Flipbook动画启动器
/// 用于非循环的Flipbook动画,在对象激活时自动设置_StartTime,使动画从当前时间开始播放
///
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(true);
}
else
{
var renderer = GetComponent();
_renderers = renderer != null ? new[] { renderer } : new Renderer[0];
}
}
private void OnEnable()
{
if (autoSetOnEnable)
{
SetStartTime();
}
}
///
/// 手动设置动画开始时间
///
public void SetStartTime()
{
SetStartTime(Time.time);
}
///
/// 设置指定的开始时间
///
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);
}
}
}
///
/// 重置动画到第一帧
///
public void ResetAnimation()
{
SetStartTime(0f);
}
///
/// 从当前时间重新播放动画
///
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
}