news 2026/4/22 21:12:39

Animation控制单条动画播放(手动设置起始帧、结束帧)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Animation控制单条动画播放(手动设置起始帧、结束帧)

代码如下:

using System.Collections; using UnityEngine; // 强制挂载Animation组件,避免忘记添加 [RequireComponent(typeof(Animation))] public class Test : MonoBehaviour { private Animation _anim; // 自身的Animation组件 private AnimationState _animState;// 要控制的单条动画状态(核心控制对象) public string animClipName = ""; // 要控制的动画片段名(和Animation组件中一致,空则用默认片段) public float animFrameRate = 30f; // 【配置】动画帧率(Animation窗口查看的数值) private float _startTime; // 实时计算的起始时间(秒) private float _stopTime; // 实时计算的停止时间(秒) private bool _isPlaying = false; // 动画播放状态标记 void Start() { // 初始化组件和动画状态(只执行一次,无需重复初始化) _anim = GetComponent<Animation>(); InitAnimState(); // 初始化动画为单次播放 if (_animState != null) _animState.wrapMode = WrapMode.Once; // 【调用示例1】立即播放:从0帧开始,30帧停止(无延时) // StartCoroutine(PlayAnimFromSpecifiedFrame(0, 30)); // 【调用示例2】延时播放:延时2秒,从5帧开始,40帧停止 StartCoroutine(PlayAnimFromSpecifiedFrame(450, 500, 2f)); } void Update() { // 动画正在播放时,逐帧检测是否到达停止帧(逻辑不变,复用实时计算的_stopTime) if (_isPlaying && _animState != null) { if (_animState.time >= _stopTime) { PauseAnim(); Debug.Log($"动画已在{Mathf.Round(_stopTime * animFrameRate)}帧停止"); } } } #region 初始化AnimationState(逻辑完全不变) private void InitAnimState() { if (_anim == null || _anim.GetClipCount() == 0) { Debug.LogError("请先给Animation组件添加动画片段!", gameObject); return; } if (string.IsNullOrEmpty(animClipName)) { animClipName = _anim.clip.name; _animState = _anim[animClipName]; } else { _animState = _anim[animClipName]; if (_animState == null) { Debug.LogError($"Animation组件中未找到名为{animClipName}的动画片段!", gameObject); } } } #endregion #region 核心改造:协程版 - 带延时+实时帧参数 播放动画 /// <summary> /// 协程版:指定帧区间播放动画,支持延时调用,实时传帧参数 /// </summary> /// <param name="startFrame">本次播放的起始帧(实时传参)</param> /// <param name="stopFrame">本次播放的停止帧(实时传参)</param> /// <param name="delay">延时播放时间(秒),默认0=立即播放</param> /// <returns>协程迭代器</returns> public IEnumerator PlayAnimFromSpecifiedFrame(int startFrame, int stopFrame, float delay = 0f) { // 前置校验:动画状态为空/帧参数非法,直接退出 if (_animState == null) yield break; if (startFrame < 0 || stopFrame < 0) { Debug.LogError("帧参数不能为负数!", gameObject); yield break; } if (startFrame > stopFrame) { Debug.LogError("起始帧不能大于停止帧!", gameObject); yield break; } // 第一步:延时逻辑(delay>0时等待,默认0则直接执行) if (delay > 0f) { Debug.Log($"动画将延时{delay}秒播放,区间:{startFrame}帧 → {stopFrame}帧"); yield return new WaitForSeconds(delay); } // 第二步:实时计算帧对应的时间(核心:不再依赖Inspector配置,随参数变化) _startTime = startFrame / animFrameRate; _stopTime = stopFrame / animFrameRate; // 第三步:停止其他动画,重置并播放当前动画(重复调用自动重置) _anim.Play(animClipName, PlayMode.StopAll); // 停止其他动画,避免冲突 _animState.time = _startTime; // 跳转到实时传入的起始帧 _animState.speed = 1f; // 恢复播放速度 _isPlaying = true; // 更新播放状态 Debug.Log($"动画{animClipName}开始播放,区间:{startFrame}帧 → {stopFrame}帧"); } #endregion #region 手动控制:播放/暂停/重新播放(逻辑完全不变,可正常使用) public void PauseAnim() { if (_animState == null || !_isPlaying) return; _animState.speed = 0f; _isPlaying = false; } public void ResumeAnim() { if (_animState == null || _isPlaying) return; _animState.speed = 1f; _isPlaying = true; } /// <summary> /// 重新播放指定帧区间(封装协程调用,方便外部直接调用) /// </summary> /// <param name="startFrame">起始帧</param> /// <param name="stopFrame">停止帧</param> /// <param name="delay">延时时间</param> public void ReplayAnim(int startFrame, int stopFrame, float delay = 0f) { StartCoroutine(PlayAnimFromSpecifiedFrame(startFrame, stopFrame, delay)); } #endregion #region 辅助方法(帧转时间,备用) private float FrameToTime(int frame) { return frame / animFrameRate; } #endregion // 编辑器调试:实时显示当前播放帧(适配实时传参的帧区间) void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position + Vector3.up * 2, 0.5f); float currentFrame = _animState == null ? 0 : Mathf.Round(_animState.time * animFrameRate); UnityEditor.Handles.Label(transform.position + Vector3.up * 3, $"当前帧:{currentFrame}\n本次停止帧:{Mathf.Round(_stopTime * animFrameRate)}"); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/16 15:00:03

计算机毕业设计springboot租房数据可视化系统 基于SpringBoot的房屋租赁信息智能分析与展示平台 Java Web驱动的城市租房数据挖掘与可视化管理系统

计算机毕业设计springboot租房数据可视化系统283pjx56 &#xff08;配套有源码 程序 mysql数据库 论文&#xff09; 本套源码可以在文本联xi,先看具体系统功能演示视频领取&#xff0c;可分享源码参考。 随着城市化进程的加速和人口流动性的增加&#xff0c;租房市场在全球经济…

作者头像 李华
网站建设 2026/4/18 15:54:31

如何用AR虚拟形象打造开发者IP?2026元宇宙营销

当测试工程师遇见虚拟分身 2026年元宇宙营销已从技术噱头进阶为品牌生态工具&#xff0c;AR虚拟形象凭借高沉浸感与强互动性&#xff0c;成为开发者IP塑造的新引擎。对软件测试从业者而言&#xff0c;虚拟IP不仅是技术能力的可视化载体&#xff0c;更是连接行业、传递专业价值…

作者头像 李华
网站建设 2026/4/18 20:34:53

ue 不同版本兼容性测试总结

目录 自动绑定变白的问题分析&#xff1a; 常见不兼容点 1️⃣ 骨骼 / ControlRig 版本变化 2️⃣ 材质系统变化 自动绑定变白的问题分析&#xff1a; 有个 Metahuman_Character 下载后进行自动绑定&#xff0c;出现皮肤变白的现象&#xff0c;换成正确版本就好了。 常见不…

作者头像 李华
网站建设 2026/4/18 13:21:25

中小品牌必备!2026年高性价比软文推广平台TOP5

对于预算有限的中小品牌&#xff0c;软文推广是实现品牌曝光与产品营销的性价比之选。然而&#xff0c;市场上发稿平台众多、质量参差&#xff0c;如何选择可靠、高效且能最大化预算价值的合作伙伴&#xff0c;成为市场决策者的关键挑战。真正的“高性价比”应是资源精准度、执…

作者头像 李华
网站建设 2026/4/19 16:56:32

模运算

lc3345 直接 n) % n 会越界&#xff0c;要 % n n) % n]; // 保证结果在 [0,n-1] 中 class Solution { public: vector<int> constructTransformedArray(vector<int>& nums) { int n nums.size(); vector<int> result(n); …

作者头像 李华