Unity3D中如何为已有移动脚本的角色实现跳跃和下蹲功能
Unity CharacterController 跳跃与下蹲功能实现方案
跳跃功能实现要点
- CharacterController 组件不自带重力模拟,需要自行维护垂直方向速度变量实现下落与跳跃逻辑
- 新增可配置参数:重力值
gravity、跳跃高度jumpHeight,新增私有变量存储垂直速度yVelocity - 每帧通过
controller.isGrounded判断角色是否接地,接地时将垂直速度置为小负值,避免地面判定异常 - 检测到跳跃输入(默认Space键)且角色接地时,通过自由落体公式反推初始跳跃速度,实现指定高度的跳跃
- 每帧将重力叠加到垂直速度,最终合并到
controller.Move的位移参数中生效
下蹲功能实现要点
- 新增可配置参数:下蹲高度
crouchHeight、下蹲移速crouchSpeed、下蹲触发键crouchKey,新增私有变量存储站立状态的控制器原始高度、原始移速 - 按下下蹲键时,直接修改CharacterController的高度为下蹲高度,同步降低移动速度
- 松开下蹲键时,先通过射线检测角色头顶是否存在障碍物,无遮挡时再还原控制器高度和移速,避免出现穿模问题
- 可根据项目需求同步修改角色模型缩放、播放下蹲动画,匹配视觉表现
完整修改后的代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Movement : MonoBehaviour { public CharacterController controller; public Transform cam; public float speed = 6f; public float turnsmoothT = 0.1f; // 跳跃相关参数 public float gravity = -9.81f; public float jumpHeight = 2f; // 下蹲相关参数 public float crouchHeight = 1f; public float crouchSpeed = 3f; public KeyCode crouchKey = KeyCode.LeftControl; float turnsmoothV; private float yVelocity; private float originalHeight; private float originalSpeed; void Start() { // 初始化记录原始高度与移速 originalHeight = controller.height; originalSpeed = speed; } void Update() { float horizontal = Input.GetAxisRaw("Horizontal"); float vertical = Input.GetAxisRaw("Vertical"); Vector3 direction = new Vector3(horizontal, 0f, vertical).normalized; bool isGrounded = controller.isGrounded; // 接地时重置垂直速度,避免判定异常 if (isGrounded && yVelocity < 0) { yVelocity = -2f; } // 跳跃逻辑 if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { yVelocity = Mathf.Sqrt(jumpHeight * -2f * gravity); } // 下蹲逻辑 if (Input.GetKeyDown(crouchKey)) { controller.height = crouchHeight; speed = crouchSpeed; } if (Input.GetKeyUp(crouchKey)) { // 检测头顶是否有障碍物,避免穿模 bool hasObstacleAbove = Physics.Raycast(transform.position, Vector3.up, originalHeight - controller.height); if (!hasObstacleAbove) { controller.height = originalHeight; speed = originalSpeed; } } if (direction.magnitude >= 0.1f) { float targetAngle = Mathf.Atan2(direction.x, direction.z) * Mathf.Rad2Deg + cam.eulerAngles.y; float angle = Mathf.SmoothDampAngle(transform.eulerAngles.y, targetAngle, ref turnsmoothV, turnsmoothT); transform.rotation = Quaternion.Euler(0f, angle, 0f); Vector3 moveDir = Quaternion.Euler(0f, targetAngle, 0f) * Vector3.forward; controller.Move(moveDir.normalized * speed * Time.deltaTime); } // 应用重力与垂直速度 yVelocity += gravity * Time.deltaTime; controller.Move(Vector3.up * yVelocity * Time.deltaTime); } }
内容的提问来源于stack exchange,提问作者ibrahemassa2
相关产品推荐
相关产品推荐

