Unity 2020.2.7f播放模式下触发动画异常及后续相关问题求助
问题描述
我需要实现一个触发式动画,流程为「上升>旋转>上升」。参考相关教程操作后,首次运行正常,但后续加载出现异常:
- 在**Play Mode(播放模式)**下,动画仅执行「上升」部分,无法完成后续的旋转和上升动作;
- 在**Inspector Mode(检视器模式)**中,动画可以正常完整播放。
我尝试过重新创建动画、重写相同代码、升级Unity版本至2020.2.6-2020.2.7,但均未解决问题。以下是动画触发控制器代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PG_animationV3 : MonoBehaviour { [SerializeField] private Animator Pg = null; [SerializeField] private bool Pg_anim_trigger = false; [SerializeField] private bool Pg_anim_trigger_down = false; private void OnTriggerEnter(Collider other) { if (Pg_anim_trigger) { Pg.Play("PG_animatorcs",0 ,0 ); } else if (Pg_anim_trigger_down) { Pg.Play("PG_animatoipnv2anim", 0 ,0 ); } } }
更新记录
3/10/21
将立方体挂载到带有动画的父物体下后,动画问题得到解决,但出现新错误Animator.GotoState:State could not be found,且立方体无法显示(相机动画运行正常)。
3/11/21
添加gameObject.setactive(false);并将父物体的Animator Controller设置为None后,程序不再崩溃,但现在需要设置计时器以及将玩家速度设为0。以下是玩家移动控制代码:
public class Player_controls : MonoBehaviour { GameObject Player; public Rigidbody rb; public Vector3 po; public float forwardMovement = 1050f; public float sidewayMovement = 660f; public float Jumpmovement = 5.01f; public float Speed = 50; void OntriggerEnter(Collider other) { if(other.gameObject.CompareTag("Power-up")) { forwardMovement = 0; } } public void FixedUpdate() { rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime); } }
现寻求针对上述一系列问题的完整解决方案。
完整解决方案
我来一步步帮你解决这些问题:
1. 修复动画仅执行部分动作的核心问题
你的初始动画断层问题,大概率是状态机过渡逻辑不严谨加上OnTriggerEnter重复触发导致动画被强制重置:
- 先检查Animator状态机:确保「上升→旋转→上升」的每一步过渡都正确设置。比如第一个上升状态结束后,要通过
Exit Time(勾选并设置为1)或者动画事件触发参数来过渡到旋转状态;旋转状态结束后同理过渡到第二个上升状态,不要留空或者设置错误的过渡条件。 - 修改触发逻辑,防止重复触发打断动画:添加一个标记变量,确保同一时间只播放一次动画,代码调整如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PG_animationV3 : MonoBehaviour { [SerializeField] private Animator Pg = null; [SerializeField] private bool Pg_anim_trigger = false; [SerializeField] private bool Pg_anim_trigger_down = false; private bool isAnimPlaying = false; // 标记动画是否正在播放 private void OnTriggerEnter(Collider other) { if (isAnimPlaying) return; // 如果动画正在播放,直接返回 if (Pg_anim_trigger) { isAnimPlaying = true; Pg.Play("PG_animatorcs", 0, 0); // 记得在动画的最后一帧添加动画事件,调用ResetAnimFlag()方法重置标记 } else if (Pg_anim_trigger_down) { isAnimPlaying = true; Pg.Play("PG_animatoipnv2anim", 0, 0); } } // 动画事件调用的方法,需要在Animator的动画片段中添加事件 public void ResetAnimFlag() { isAnimPlaying = false; } } - 检查Animator的Update Mode:设置为
Normal,避免和FixedUpdate的时序冲突导致动画播放异常。
2. 解决Animator.GotoState:State could not be found错误
这个错误是状态名称不匹配或者Animator Controller缺失状态导致的:
- 核对状态名称:仔细检查
PG_animatorcs和PG_animatoipnv2anim这两个名称,和你Animator Controller里的状态名称完全一致吗?比如PG_animatoipnv2anim看起来像是拼写错误(多了个i?),一定要确保大小写、拼写完全相同。 - 立方体无法显示的排查:检查立方体的
Mesh Renderer是否启用,父物体的缩放/位置是否把立方体移出了相机视野,或者立方体的Layer被相机的Culling Mask排除了。
3. 实现计时器与玩家速度控制
你的玩家控制代码有个明显的拼写错误,而且缺少计时器逻辑,我帮你调整完善:
public class Player_controls : MonoBehaviour { public Rigidbody rb; public float forwardMovement = 1050f; public float sidewayMovement = 660f; public float Jumpmovement = 5.01f; public float Speed = 50; public float powerUpDuration = 3f; // 可以自定义Power-up的持续时间 private float originalForwardSpeed; // 保存初始速度 private Coroutine speedCoroutine; // 用于管理计时器协程 void Start() { originalForwardSpeed = forwardMovement; // 初始化时保存初始速度 rb = GetComponent<Rigidbody>(); // 直接获取自身的Rigidbody,避免空引用 } // 注意这里是大写的O!之前的OntriggerEnter是拼写错误,Unity识别不了 private void OnTriggerEnter(Collider other) { if(other.gameObject.CompareTag("Power-up")) { // 如果之前有计时器在运行,先停止它,避免重复触发 if (speedCoroutine != null) StopCoroutine(speedCoroutine); forwardMovement = 0; // 立即归零速度 speedCoroutine = StartCoroutine(ResetSpeedAfterDelay(powerUpDuration)); Destroy(other.gameObject); // 销毁Power-up,防止重复触发 } } // 协程实现延迟恢复速度 private IEnumerator ResetSpeedAfterDelay(float delay) { yield return new WaitForSeconds(delay); forwardMovement = originalForwardSpeed; // 恢复初始速度 } public void FixedUpdate() { rb.AddForce(0, 0, forwardMovement * Speed * Time.deltaTime); } }
- 额外注意:Power-up对象必须有
Collider(勾选Is Trigger),如果是静态物体,需要添加Rigidbody并勾选Kinematic,否则OnTriggerEnter不会触发。
4. 父物体Animator的最优设置
你之前把父物体的Animator Controller设为None,这不是长久之计:
- 如果父物体本身不需要动画,直接移除它的Animator组件,避免不必要的错误;
- 如果父物体需要动画,确保它的Animator Controller包含你要调用的所有状态,并且状态名称完全匹配。
内容的提问来源于stack exchange,提问作者Fire-Source




