Unity3D爬墙功能欧拉角限制异常:进入触发器时视角骤跳
爬墙视角骤跳问题修复方案
问题根源很明确:你进入爬墙状态时,直接把玩家Y轴角度硬卡到全局固定的[-20,20]区间,不管玩家当时朝向哪里,自然会出现视角跳变。下面给两种可行的修复思路:
思路1:基于爬墙初始朝向限制旋转
进入爬墙状态时,先记录玩家当前的Y轴角度作为基准,后续只允许在这个基准的±20度范围内旋转,避免硬拉视角。
修改代码如下:
private float minYRot = -20f; private float maxYRot = 20f; // 新增:记录爬墙开始时的基准Y轴角度 private float climbStartYRot; // 替换原来的触发调用逻辑,进入触发器时调用这个方法初始化基准角度 public void StartWallClimb() { wallClimb.climbing = true; // 把当前玩家Y轴角度转成-180到180的范围 float currentY = player.rotation.eulerAngles.y; climbStartYRot = currentY > 180 ? currentY - 360 : currentY; } public void LateUpdate() { float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime; xRotation -= mouseY; xRotation = Mathf.Clamp(xRotation, -90f, 90f); transform.eulerAngles = new Vector3(xRotation, player.rotation.eulerAngles.y, 0f); // 分状态处理旋转:非爬墙正常转,爬墙时按限制规则转 if (!wallClimb.climbing) { player.transform.Rotate(Vector3.up * mouseX); } else { LimitRotation(mouseX); } } // 修改限制逻辑,基于基准角度做范围约束 public void LimitRotation(float mouseX) { float currentY = player.rotation.eulerAngles.y; currentY = currentY > 180 ? currentY - 360 : currentY; // 计算加上鼠标输入后的临时角度 float tempY = currentY + mouseX; // 基于爬墙初始角度做clamp tempY = Mathf.Clamp(tempY, climbStartYRot + minYRot, climbStartYRot + maxYRot); // 应用最终旋转 player.rotation = Quaternion.Euler(player.rotation.eulerAngles.x, tempY, player.rotation.eulerAngles.z); }
思路2:基于墙体朝向限制旋转(更符合爬墙逻辑)
爬墙时玩家的旋转应该相对于墙体朝向,比如面朝墙体时只能左右转20度。这种情况需要在进入触发器时记录墙体的朝向:
private float minYRot = -20f; private float maxYRot = 20f; // 新增:记录墙体前方向的Y轴角度(转成-180到180范围) private float wallForwardYRot; // 进入触发器时调用,传入墙体的Transform public void StartWallClimb(Transform wallTransform) { wallClimb.climbing = true; float wallY = wallTransform.forward.eulerAngles.y; wallForwardYRot = wallY > 180 ? wallY - 360 : wallY; } public void LateUpdate() { float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime; xRotation -= mouseY; xRotation = Mathf.Clamp(xRotation, -90f, 90f); transform.eulerAngles = new Vector3(xRotation, player.rotation.eulerAngles.y, 0f); if (!wallClimb.climbing) { player.transform.Rotate(Vector3.up * mouseX); } else { LimitRotation(mouseX); } } public void LimitRotation(float mouseX) { // 计算玩家当前相对于墙体的角度 float currentPlayerY = player.rotation.eulerAngles.y; currentPlayerY = currentPlayerY > 180 ? currentPlayerY - 360 : currentPlayerY; float relativeY = currentPlayerY - wallForwardYRot; // 加上鼠标输入的旋转量后限制范围 relativeY += mouseX; relativeY = Mathf.Clamp(relativeY, minYRot, maxYRot); // 转成全局角度应用 float targetY = wallForwardYRot + relativeY; player.rotation = Quaternion.Euler(player.rotation.eulerAngles.x, targetY, player.rotation.eulerAngles.z); }
补充触发器调用逻辑
需要在墙体触发器的OnTriggerEnter方法里调用初始化方法,而不是直接在LateUpdate里触发限制:
private void OnTriggerEnter(Collider other) { if (other.CompareTag("Wall")) { // 用思路1就调用StartWallClimb(),思路2则传墙体Transform StartWallClimb(other.transform); } }
内容的提问来源于stack exchange,提问作者dangoqut132
相关产品推荐
相关产品推荐

