128 lines
3.4 KiB
C#
128 lines
3.4 KiB
C#
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
|
||
}
|
||
|