You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity如何通过反向播放中断正在运行的动画

问题背景

某GameObject上存在两个变换状态A和B,同时配置了两个用于在两状态间过渡的动画:A->B与B->A,两个动画采用不同的动画曲线,用户可在任意时刻修改该GameObject的状态。

实现目标
  • 无动画播放时修改状态:正常播放A->B或B->A动画即可
  • 动画播放过程中修改状态:将当前正在播放的动画反向播放实现中断,而非切换到对应方向的另一段动画

举例说明:用户将状态切换为B时开始播放A->B动画,若该动画播放完成前用户突然切回A状态,此时需要A->B动画直接反向播放回到A状态,而非播放B->A动画。

当前进展

目前已尝试使用Unity原生Animator组件,但未找到可反向播放正在运行动画的相关接口;除Animator外也可接受其他原生实现方案,优先不使用任何外部第三方库。

当前仅实现A、B状态切换、未加入反向播放逻辑的代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAnimation : MonoBehaviour
{
    private Animator _animator;

    private bool _isOpen = true;

    void Awake()
    {
        this._animator = GetComponent<Animator>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            if (this._isOpen)
                this._animator.SetTrigger("A");
            else
                this._animator.SetTrigger("B");

            this._isOpen = !this._isOpen;
        }
    }
}
实现方案

Animator状态机的状态切换逻辑是预定义的,动态修改当前播放动画的方向实现成本很高,直接用Unity原生Animation组件做手动播放控制是最简洁的方案,完全不需要第三方库。

实现逻辑

  1. 挂载Animation组件,关闭自动播放,将两个动画片段注册到组件中
  2. 维护当前播放的动画片段、播放速度两个核心状态
  3. 触发状态切换时做分支判断:
    • 无正在播放的动画:直接播放对应方向的动画片段,速度设为正向1
    • 有正在播放的动画:不切换动画片段,直接将当前动画的播放速度取反,动画会自动沿着原曲线从当前进度反向播放
  4. 每帧检测动画播放进度,正向播到末尾或反向退到起点时停止动画,校正最终状态避免浮点误差

完整代码

using UnityEngine;

public class TestAnimation : MonoBehaviour
{
    private Animation _animation;
    
    // 在Inspector面板拖入两个方向的动画片段
    public AnimationClip a2bClip;
    public AnimationClip b2aClip;
    
    private bool _isOpen = true;
    private AnimationClip _currentPlayingClip;
    private float _currentSpeed;

    void Awake()
    {
        _animation = GetComponent<Animation>();
        _animation.playAutomatically = false;
        // 注册动画片段
        _animation.AddClip(a2bClip, "A2B");
        _animation.AddClip(b2aClip, "B2A");
        // 初始状态对齐到A状态
        _animation["A2B"].time = 0;
        _animation.Sample();
        _animation.Stop();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            ToggleState();
        }
        CheckAnimationComplete();
    }

    void ToggleState()
    {
        _isOpen = !_isOpen;
        
        // 无播放中动画,启动对应方向的新动画
        if (_currentPlayingClip == null)
        {
            if (!_isOpen)
            {
                _currentPlayingClip = a2bClip;
                _currentSpeed = 1f;
                _animation.Play("A2B");
                _animation["A2B"].speed = _currentSpeed;
                _animation["A2B"].time = 0;
            }
            else
            {
                _currentPlayingClip = b2aClip;
                _currentSpeed = 1f;
                _animation.Play("B2A");
                _animation["B2A"].speed = _currentSpeed;
                _animation["B2A"].time = 0;
            }
        }
        // 有播放中动画,直接反向速度
        else
        {
            _currentSpeed *= -1;
            string animName = _currentPlayingClip == a2bClip ? "A2B" : "B2A";
            _animation[animName].speed = _currentSpeed;
        }
    }

    void CheckAnimationComplete()
    {
        if (_currentPlayingClip == null) return;
        
        string animName = _currentPlayingClip == a2bClip ? "A2B" : "B2A";
        AnimationState animState = _animation[animName];
        float totalLength = _currentPlayingClip.length;
        
        // 判定播放结束
        if ((_currentSpeed > 0 && animState.time >= totalLength) || (_currentSpeed < 0 && animState.time <= 0))
        {
            _animation.Stop();
            // 校正位置避免浮点偏移
            animState.time = _currentSpeed > 0 ? totalLength : 0;
            _animation.Sample();
            _currentPlayingClip = null;
        }
    }
}

配置注意事项

  • 两个动画片段的Wrap Mode需要设置为Once,不要开启循环
  • 如果不需要保留两个独立曲线的过渡动画,也可以只用一个动画片段,反向时直接倒播,代码逻辑可以进一步简化
  • 所有逻辑均使用Unity原生API实现,无额外依赖,性能表现优于Animator状态机方案

内容的提问来源于stack exchange,提问作者Adam Jonsson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 02:09:38