Unity FPS:基于Character Controller的滑铲功能实现求助
基于Character Controller的跑后滑铲实现方案(无需Rigidbody)
针对你现有基于Character Controller的FPS角色控制器,以下是无需Rigidbody的简便滑铲实现,完全复用现有逻辑,改动量小:
核心思路
滑铲本质是奔跑状态下触发的带冲量的蹲伏滑行:按下滑铲键时,立即切换到蹲伏状态,赋予一个高于奔跑速度的初始滑铲冲量,随后逐渐减速,直到滑铲结束或松开滑铲键,最后恢复站立/奔跑状态。
代码修改步骤
1. 添加滑铲相关配置变量
在现有代码对应位置插入以下变量:
[Header("Controls")] [SerializeField] private KeyCode sprintKey = KeyCode.LeftShift; [SerializeField] private KeyCode jumpKey = KeyCode.Space; [SerializeField] private KeyCode crouchKey = KeyCode.C; [SerializeField] private KeyCode slideKey = KeyCode.LeftControl; // 启用滑铲按键 [SerializeField] private KeyCode zoomKey = KeyCode.Mouse1; [Header("Movement Parameters")] [SerializeField] private float walkSpeed = 3.0f; [SerializeField] private float sprintSpeed = 6.0f; [SerializeField] private float crouchSpeed = 1.5f; [SerializeField] private float slopeSpeed = 8f; [SerializeField] private float slideSpeed = 8.0f; // 滑铲初始速度 [SerializeField] private float slideDuration = 0.5f; // 滑铲持续时间 [SerializeField] private float slideDecay = 4.0f; // 滑铲减速系数 // 滑铲状态变量 private bool isPerformingSlide; private float slideTimer; private float currentSlideSpeed;
2. 添加滑铲输入判断
在顶部布尔判断区域新增滑铲触发条件:
private bool shouldSlide => Input.GetKeyDown(slideKey) && isSpritning && characterController.isGrounded && !duringCrouchAnimation && !isPerformingSlide;
3. 新增滑铲处理逻辑
添加HandleSlide函数,并在Update中调用:
private void Update() { if (canMove) { HandleMovementInput(); HandleMouseLook(); if (canJump) { HandleJump(); } if (canCrouch) { HandleCrouch(); } // 新增滑铲处理 if (canCrouch) { HandleSlide(); } if (canUseHeadbob) { HandleHeadbob(); } if (canZoom) { HandleZoom(); } ApplyFinalMovements(); } } private void HandleSlide() { // 触发滑铲 if (shouldSlide) { isPerformingSlide = true; slideTimer = slideDuration; currentSlideSpeed = slideSpeed; // 直接进入蹲伏状态(跳过动画,提升滑铲爽快感) isCrouching = true; characterController.height = crouchHeight; characterController.center = crouchingCenter; } // 滑铲进行中逻辑 if (isPerformingSlide) { slideTimer -= Time.deltaTime; // 线性减速 currentSlideSpeed = Mathf.Lerp(currentSlideSpeed, 0, slideDecay * Time.deltaTime); // 滑铲结束条件:时间耗尽/松开滑铲键/离开地面 if (slideTimer <= 0 || Input.GetKeyUp(slideKey) || !characterController.isGrounded) { isPerformingSlide = false; // 头顶无障碍物则自动站起 if (!Physics.Raycast(playerCamera.transform.position, Vector3.up, 1f)) { isCrouching = false; characterController.height = standingHeight; characterController.center = standingCenter; } } } }
4. 修改移动输入逻辑
在HandleMovementInput中优先判断滑铲状态,替换原速度选择逻辑:
private void HandleMovementInput() { // 优先级:滑铲速度 > 蹲伏速度 > 奔跑速度 > 行走速度 float moveSpeed = isPerformingSlide ? currentSlideSpeed : isCrouching ? crouchSpeed : isSpritning ? sprintSpeed : walkSpeed; currentInput = new Vector2(moveSpeed * Input.GetAxis("Vertical"), moveSpeed * Input.GetAxis("Horizontal")); float moveDirectionY = moveDirection.y; moveDirection = (transform.TransformDirection(Vector3.forward) * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y); moveDirection.y = moveDirectionY; }
5. 修复蹲伏协程冲突
修改CrouchStand协程,避免与滑铲状态冲突:
private IEnumerator CrouchStand() { if(isCrouching && Physics.Raycast(playerCamera.transform.position, Vector3.up, 1f)) { yield break; } // 滑铲进行中不允许触发蹲伏动画 if (isPerformingSlide) yield break; duringCrouchAnimation = true; float timeElapsed = 0; float targetHeight = isCrouching ? standingHeight : crouchHeight; float currentHeight = characterController.height; Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter; Vector3 currentCenter = characterController.center; isCrouching = !isCrouching; while (timeElapsed < timeToCrouch) { characterController.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed / timeToCrouch); characterController.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed / timeToCrouch); timeElapsed += Time.deltaTime; yield return null; } characterController.height = targetHeight; characterController.center = targetCenter; duringCrouchAnimation = false; }
手感调整建议
- 调大
slideSpeed或增加slideDuration可以延长滑铲距离; - 提高
slideDecay系数会让滑铲更快停止; - 滑铲时可在
HandleHeadbob中新增滑铲状态判断,使用更急促的头部晃动参数增强反馈。
内容的提问来源于stack exchange,提问作者gitanogamer
相关产品推荐
相关产品推荐

