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 }