Unity 3D动画中途冻结异常问题求助
Unity第三人称移动动画中途冻结问题修复
问题描述
完成Unity第三人称移动与动画配置后,出现动画中途冻结异常:玩家跑步动作会卡在单腿抬起、另一腿斜伸的怪异姿势,但角色移动功能完全正常。尝试重置项目、重启工程、参考教程均未解决。
代码问题分析
Animator变换被强制重置:Update函数中每帧执行
anim.transform.localPosition = Vector3.zero;和anim.transform.localEulerAngles = Vector3.zero;,这会强制覆盖动画播放时产生的位移和旋转,直接打断动画的正常播放流程,导致动画冻结在某一帧。地面检测层掩码错误:
Physics.CheckSphere(transform.position, .1f, 1)中使用固定数值1作为层掩码,可能未正确匹配地面层,导致isGrounded状态判断异常,干扰动画状态机的切换逻辑。动画参数切换无平滑过渡:直接给
Speed参数赋值0/1/2,参数突变可能导致动画状态切换时出现卡顿或冻结。
修复方案
1. 移除Animator强制重置代码
删除Update中每帧重置Animator变换的两行代码,避免打断动画播放:
// 移除以下两行 anim.transform.localPosition = Vector3.zero; anim.transform.localEulerAngles = Vector3.zero;
2. 修正地面检测层掩码
创建专门的"Ground"层,替换固定层掩码数值,确保地面检测准确:
// 替换原地面检测代码 isGrounded = Physics.CheckSphere(transform.position, .1f, LayerMask.GetMask("Ground"));
3. 给动画参数添加平滑过渡
使用SetFloat的重载方法,让Speed参数平滑变化,避免突变:
// 替换原Speed参数赋值逻辑 float targetSpeed = direction.magnitude >= .1f ? (sprinting ? 2f : 1f) : 0f; anim.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime);
4. 检查动画状态机配置
- 确保跑步、走路动画片段开启循环(在动画导入设置中勾选Loop Time)。
- 确认动画状态机中Idle、Walk、Sprint之间的过渡条件合理,无冲突的过渡规则。
修改后的完整代码
using System; using UnityEngine; using Quaternion = UnityEngine.Quaternion; using Vector3 = UnityEngine.Vector3; public class ThirdPersonMovement : MonoBehaviour { public CharacterController controller; public float turnSmoothTime = .1f; private float turnSmoothVelocity; public float walkSpeed; public float sprintSpeed; private float trueSpeed; public Transform cam; public float jumpHeight; public float gravity; private bool isGrounded; private Vector3 velocity; public Animator anim; public bool sprinting; private void Start() { trueSpeed = walkSpeed; Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; // 仅在初始化时重置Animator变换(可选,根据需求调整) anim.transform.localPosition = Vector3.zero; anim.transform.localEulerAngles = Vector3.zero; } void Update() { // 修正地面检测层掩码 isGrounded = Physics.CheckSphere(transform.position, .1f, LayerMask.GetMask("Ground")); anim.SetBool("isGrounded", isGrounded); if (isGrounded && velocity.y < 0) { velocity.y = -1; } float horizontal = Input.GetAxisRaw("Horizontal"); float vertical = Input.GetAxisRaw("Vertical"); Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized; if (Input.GetKeyDown(KeyCode.LeftShift)) { trueSpeed = sprintSpeed; sprinting = true; } if (Input.GetKeyUp(KeyCode.LeftShift)) { trueSpeed = walkSpeed; sprinting = false; } if (direction.magnitude >= .1f) { float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y; float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnSmoothVelocity, turnSmoothTime); transform.rotation = Quaternion.Euler(0f, angle, 0f); Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward; controller.Move(moveDir * trueSpeed * Time.deltaTime); } // 平滑设置Speed参数 float targetSpeed = direction.magnitude >= .1f ? (sprinting ? 2f : 1f) : 0f; anim.SetFloat("Speed", targetSpeed, 0.1f, Time.deltaTime); if (Input.GetButtonDown("Jump") && isGrounded) { velocity.y = Mathf.Sqrt((jumpHeight * 10) * -2f * gravity); } if (velocity.y > -20) { velocity.y += (gravity * 10) * Time.deltaTime; } controller.Move(velocity * Time.deltaTime); } }
内容的提问来源于stack exchange,提问作者TurtleLover69
相关产品推荐
相关产品推荐

