charactercontroller move y 会上升

charactercontroller move y 会上升 

角色控制器中的变量:
isGrounded: 着地,在最后的移动角色控制器是否接触地面;
velocity:角色当前的相对速度;
cllisionFlags:在最后的characterController.Move调用期间,胶囊提的哪个部分和周围环境相碰撞。
radius:角色胶囊体 的半径,
height:角色胶囊体的高度。
center:相对于变换位置的角色胶囊体的中心。
slopLimit:角色控制器的坡度洗漱限制,
stepOffest:以米为单位的角色控制器的台阶偏移量
using UnityEngine; using UnityEngine.UI; using System.Collections; [RequireComponent(typeof(CharacterController))] public class _3DPresonMode : MonoBehaviour { [Header("References")] public Camera mainCamera; public GameObject playerModel; public BoxCollider groundCollider; public Button toggleButton; [Header("Settings")] public float moveSpeed = 5f; public float mouseSensitivity = 2f; public float minCameraHeight = 0.5f; public float transitionDuration = 1f; [Header("Rotation Settings")] public bool requireRightClick = true; // 是否需要按住右键旋转 public bool lockCursor = true; // 是否锁定鼠标光标 // 状态变量 private bool isActive = false; private Vector3 initialCameraPosition; private Quaternion initialCameraRotation; private CharacterController characterController; private float rotationX = 0f; private float groundHeight; private Coroutine transitionCoroutine; private Text buttonText; private bool isRotating = false; // 当前是否正在旋转 [Header("Vertical Movement")] public float verticalSpeed = 3f; // 垂直移动速度 public float maxHeight = 25f; // 最大高度限制 public float minHeightOffset = 0.2f; // 最小高度偏移(防止穿透地面) void Start() { // 获取必要组件 characterController = playerModel.GetComponent<CharacterController>(); if (characterController == null) { characterController = playerModel.AddComponent<CharacterController>(); characterController.height = 2f; characterController.radius = 0.5f; characterController.center = Vector3.up; } // 保存初始相机状态 initialCameraPosition = mainCamera.transform.position; initialCameraRotation = mainCamera.transform.rotation; // 计算地面高度 if (groundCollider != null) { groundHeight = groundCollider.bounds.max.y; } else { Debug.LogError("Ground Collider not assigned!"); groundHeight = 0f; } // 设置按钮 if (toggleButton != null) { buttonText = toggleButton.GetComponentInChildren<Text>(); toggleButton.onClick.AddListener(ToggleMode); UpdateButtonText(); } else { Debug.LogError("Toggle button not assigned!"); } // 初始光标状态 UpdateCursorState(); } public void ToggleMode() { isActive = !isActive; if (transitionCoroutine != null) { StopCoroutine(transitionCoroutine); } if (isActive) { transitionCoroutine = StartCoroutine(EnterFirstPersonMode()); } else { transitionCoroutine = StartCoroutine(ExitFirstPersonMode()); } UpdateButtonText(); UpdateCursorState(); } private IEnumerator EnterFirstPersonMode() { // 保存当前相机状态作为过渡起点 Vector3 startPos = mainCamera.transform.position; Quaternion startRot = mainCamera.transform.rotation; // 计算目标位置和旋转 Vector3 targetPos = playerModel.transform.position + Vector3.up * 1.7f; Quaternion targetRot = playerModel.transform.rotation; // 平滑过渡 float elapsed = 0f; while (elapsed < transitionDuration) { float t = elapsed / transitionDuration; mainCamera.transform.position = Vector3.Lerp(startPos, targetPos, t); mainCamera.transform.rotation = Quaternion.Slerp(startRot, targetRot, t); elapsed += Time.deltaTime; yield return null; } // 最终设置 mainCamera.transform.SetParent(playerModel.transform); mainCamera.transform.localPosition = Vector3.up * 1.7f; mainCamera.transform.localRotation = Quaternion.identity; rotationX = 0f; isRotating = false; } private IEnumerator ExitFirstPersonMode() { // 解除相机父子关系 mainCamera.transform.SetParent(null); // 保存当前相机状态作为过渡起点 Vector3 startPos = mainCamera.transform.position; Quaternion startRot = mainCamera.transform.rotation; // 平滑过渡回初始位置 float elapsed = 0f; while (elapsed < transitionDuration) { float t = elapsed / transitionDuration; mainCamera.transform.position = Vector3.Lerp(startPos, initialCameraPosition, t); mainCamera.transform.rotation = Quaternion.Slerp(startRot, initialCameraRotation, t); elapsed += Time.deltaTime; yield return null; } // 最终设置 mainCamera.transform.position = initialCameraPosition; mainCamera.transform.rotation = initialCameraRotation; isRotating = false; } void Update() { if (!isActive) return; HandleMovement(); HandleRotation(); HandleVerticalMovement(); // 添加垂直移动处理 // PreventCameraGroundPenetration(); // 不再需要此方法 } // 新增的垂直移动处理方法 private void HandleVerticalMovement() { float verticalInput = 0f; // 检测按键输入 if (Input.GetKey(KeyCode.Space)) verticalInput = 1f; // 上升 if (Input.GetKey(KeyCode.E)) verticalInput = -1f; // 下降 // 如果没有输入,则不需要移动 if (verticalInput == 0f) return; // 计算目标高度 float targetHeight = playerModel.transform.position.y + verticalInput * verticalSpeed * Time.deltaTime; // 获取地面高度 float currentGroundHeight = GetGroundHeight(); // 应用高度限制 targetHeight = Mathf.Clamp( targetHeight, currentGroundHeight + minHeightOffset, // 最低高度(地面高度 + 偏移) maxHeight // 最高高度 ); // 应用新的高度 Vector3 newPosition = playerModel.transform.position; newPosition.y = targetHeight; playerModel.transform.position = newPosition; } // 获取当前玩家位置下的地面高度 private float GetGroundHeight() { if (groundCollider == null) return 0f; // 创建从玩家位置向下发射的射线 Vector3 rayOrigin = playerModel.transform.position; rayOrigin.y = groundCollider.bounds.max.y + 1f; // 从碰撞器上方开始 // 射线检测 if (Physics.Raycast(rayOrigin, Vector3.down, out RaycastHit hit, Mathf.Infinity)) { // 确保只检测地面碰撞器 if (hit.collider == groundCollider) { return hit.point.y; } } // 如果射线未命中,返回碰撞器顶部高度 return groundCollider.bounds.max.y; } private void HandleMovement() { Vector3 moveDirection = Vector3.zero; if (Input.GetKey(KeyCode.W)) moveDirection += playerModel.transform.forward; if (Input.GetKey(KeyCode.S)) moveDirection -= playerModel.transform.forward; if (Input.GetKey(KeyCode.D)) moveDirection += playerModel.transform.right; if (Input.GetKey(KeyCode.A)) moveDirection -= playerModel.transform.right; if (moveDirection != Vector3.zero) { characterController.SimpleMove(moveDirection.normalized * moveSpeed); } } private void HandleRotation() { // 检查旋转开始条件 if (requireRightClick) { // 右键按下时开始旋转 if (Input.GetMouseButtonDown(1)) { isRotating = true; UpdateCursorState(); } // 右键释放时停止旋转 else if (Input.GetMouseButtonUp(1)) { isRotating = false; UpdateCursorState(); } } else { // 不需要右键,直接激活旋转 isRotating = true; } // 只有旋转激活时才处理输入 if (!isRotating) return; float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity; float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity; // 水平旋转(转动整个玩家模型) playerModel.transform.Rotate(Vector3.up, mouseX); // 垂直旋转(仅旋转相机) rotationX -= mouseY; rotationX = Mathf.Clamp(rotationX, -90f, 90f); // 限制俯仰角 mainCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0); } private void UpdateButtonText() { if (buttonText != null) { buttonText.text = isActive ? "退出" : "巡游"; } } private void UpdateCursorState() { if (!isActive) { // 非第一人称模式:显示光标 Cursor.lockState = CursorLockMode.None; Cursor.visible = true; return; } if (lockCursor) { // 第一人称模式:根据旋转状态设置光标 if (isRotating || !requireRightClick) { Cursor.lockState = CursorLockMode.Locked; Cursor.visible = false; } else { Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } } else { // 不锁定光标 Cursor.lockState = CursorLockMode.None; Cursor.visible = true; } } // 在Inspector中添加调试按钮 [ContextMenu("Fix Rotation")] public void DebugFixRotation() { rotationX = 0f; mainCamera.transform.localRotation = Quaternion.identity; Debug.Log("Camera rotation reset to default"); } } 【出现按键移动错乱的现象,检查代码,修复问题】
最新发布
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值