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
|
|||
|
|
}
|
|||
|
|
|