角色控制

This commit is contained in:
2025-05-29 21:10:30 +08:00
parent cdcb007d6d
commit 8d3cfe170c
6 changed files with 463 additions and 401 deletions

View File

@@ -4,7 +4,7 @@ namespace EasyPeasyFirstPersonController
using System.Collections;
using UnityEngine;
public partial class FirstPersonController : MonoBehaviour
public class FirstPersonController : MonoBehaviour
{
[Range(0, 100)] public float mouseSensitivity = 25f;
[Range(0f, 200f)] private float snappiness = 100f;
@@ -55,7 +55,6 @@ namespace EasyPeasyFirstPersonController
private Camera cam;
private AudioSource slideAudioSource;
private float bobTimer;
private float defaultPosY;
private Vector3 recoil = Vector3.zero;
private bool isLook = true, isMove = true;
private float currentCameraHeight;
@@ -67,15 +66,13 @@ namespace EasyPeasyFirstPersonController
private float currentTiltAngle;
private float tiltVelocity;
public float CurrentCameraHeight => isCrouching || isSliding ? crouchCameraHeight : originalCameraParentHeight;
private void Awake()
{
characterController = GetComponent<CharacterController>();
cam = playerCamera.GetComponent<Camera>();
originalHeight = characterController.height;
originalCameraParentHeight = cameraParent.localPosition.y;
defaultPosY = cameraParent.localPosition.y;
// defaultPosY = cameraParent.localPosition.y;
slideAudioSource = gameObject.AddComponent<AudioSource>();
slideAudioSource.playOnAwake = false;
slideAudioSource.loop = false;
@@ -118,10 +115,11 @@ namespace EasyPeasyFirstPersonController
transform.rotation = Quaternion.Euler(0f, xVelocity, 0f);
}
HandleHeadBob();
// HandleHeadBob();
bool wantsToCrouch = canCrouch && Input.GetKey(KeyCode.LeftControl) && !isSliding;
Vector3 point1 = transform.position + characterController.center - Vector3.up * (characterController.height * 0.5f);
Vector3 point1 = transform.position + characterController.center -
Vector3.up * (characterController.height * 0.5f);
Vector3 point2 = point1 + Vector3.up * characterController.height * 0.6f;
float capsuleRadius = characterController.radius * 0.95f;
float castDistance = isSliding ? originalHeight + 0.2f : originalHeight - crouchHeight + 0.2f;
@@ -130,6 +128,7 @@ namespace EasyPeasyFirstPersonController
{
postSlideCrouchTimer = 0.3f;
}
if (postSlideCrouchTimer > 0)
{
postSlideCrouchTimer -= Time.deltaTime;
@@ -144,7 +143,9 @@ namespace EasyPeasyFirstPersonController
{
isSliding = true;
slideTimer = slideDuration;
slideDirection = moveInput.magnitude > 0.1f ? (transform.right * moveInput.x + transform.forward * moveInput.y).normalized : transform.forward;
slideDirection = moveInput.magnitude > 0.1f
? (transform.right * moveInput.x + transform.forward * moveInput.y).normalized
: transform.forward;
currentSlideSpeed = sprintSpeed;
}
@@ -156,6 +157,7 @@ namespace EasyPeasyFirstPersonController
{
isSliding = false;
}
float targetSlideSpeed = slideSpeed * Mathf.Lerp(0.7f, 1f, slideProgress);
currentSlideSpeed = Mathf.SmoothDamp(currentSlideSpeed, targetSlideSpeed, ref slideSpeedVelocity, 0.2f);
characterController.Move(slideDirection * currentSlideSpeed * Time.deltaTime);
@@ -165,7 +167,9 @@ namespace EasyPeasyFirstPersonController
characterController.height = Mathf.Lerp(characterController.height, targetHeight, Time.deltaTime * 10f);
characterController.center = new Vector3(0f, characterController.height * 0.5f, 0f);
float targetFov = isSprinting ? sprintFov : (isSliding ? sprintFov + (slideFovBoost * Mathf.Lerp(0f, 1f, 1f - slideProgress)) : normalFov);
float targetFov = isSprinting
? sprintFov
: (isSliding ? sprintFov + (slideFovBoost * Mathf.Lerp(0f, 1f, 1f - slideProgress)) : normalFov);
currentFov = Mathf.SmoothDamp(currentFov, targetFov, ref fovVelocity, 1f / fovChangeSpeed);
cam.fieldOfView = currentFov;
@@ -174,7 +178,8 @@ namespace EasyPeasyFirstPersonController
private void HandleHeadBob()
{
Vector3 horizontalVelocity = new Vector3(characterController.velocity.x, 0f, characterController.velocity.z);
Vector3 horizontalVelocity =
new Vector3(characterController.velocity.x, 0f, characterController.velocity.z);
bool isMovingEnough = horizontalVelocity.magnitude > 0.1f;
float targetBobOffset = isMovingEnough ? Mathf.Sin(bobTimer) * bobbingAmount : 0f;
@@ -190,7 +195,8 @@ namespace EasyPeasyFirstPersonController
currentCameraHeight + currentBobOffset,
cameraParent.localPosition.z);
recoil = Vector3.zero;
cameraParent.localRotation = Quaternion.RotateTowards(cameraParent.localRotation, Quaternion.Euler(recoil), recoilReturnSpeed * Time.deltaTime);
cameraParent.localRotation = Quaternion.RotateTowards(cameraParent.localRotation,
Quaternion.Euler(recoil), recoilReturnSpeed * Time.deltaTime);
return;
}
@@ -218,14 +224,16 @@ namespace EasyPeasyFirstPersonController
recoil = Vector3.zero;
}
cameraParent.localRotation = Quaternion.RotateTowards(cameraParent.localRotation, Quaternion.Euler(recoil), recoilReturnSpeed * Time.deltaTime);
cameraParent.localRotation = Quaternion.RotateTowards(cameraParent.localRotation, Quaternion.Euler(recoil),
recoilReturnSpeed * Time.deltaTime);
}
private void HandleMovement()
{
moveInput.x = Input.GetAxis("Horizontal");
moveInput.y = Input.GetAxis("Vertical");
isSprinting = canSprint && Input.GetKey(KeyCode.LeftShift) && moveInput.y > 0.1f && isGrounded && !isCrouching && !isSliding;
isSprinting = canSprint && Input.GetKey(KeyCode.LeftShift) && moveInput.y > 0.1f && isGrounded &&
!isCrouching && !isSliding;
float currentSpeed = isCrouching ? crouchSpeed : (isSprinting ? sprintSpeed : walkSpeed);
if (!isMove) currentSpeed = 0f;
@@ -256,27 +264,5 @@ namespace EasyPeasyFirstPersonController
characterController.Move(moveDirection * Time.deltaTime);
}
}
public void SetControl(bool newState)
{
SetLookControl(newState);
SetMoveControl(newState);
}
public void SetLookControl(bool newState)
{
isLook = newState;
}
public void SetMoveControl(bool newState)
{
isMove = newState;
}
public void SetCursorVisibility(bool newVisibility)
{
Cursor.lockState = newVisibility ? CursorLockMode.None : CursorLockMode.Locked;
Cursor.visible = newVisibility;
}
}
}

View File

@@ -4635,7 +4635,7 @@ MonoBehaviour:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5559475303044247694}
m_Enabled: 0
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 776adaaacdc5c4e8ab0395120a6e972b, type: 3}
m_Name:

View File

@@ -1,4 +1,6 @@
using NBC;
using System;
using NBC;
using RootMotion.FinalIK;
using UnityEngine;
namespace NBF
@@ -16,9 +18,20 @@ namespace NBF
private FPlayer _player;
private bool _isRun;
public LookAtIK lookAtIK; // 挂在背部上的 LookAtIK 脚本
public float aimDistance = 1.5f; // 目标点离相机多远
private Transform lookTarget; // 实际目标点
[Header("限制角度(单位:度)")] public float maxUpAngle = 20f; // 相机抬头最多20°
public float maxDownAngle = 40f; // 相机低头最多40°
public LayerMask interactableLayer;
private void Start()
{
firstPersonController = GetComponent<FirstPersonController>();
@@ -41,6 +54,11 @@ namespace NBF
InputManager.OnPlayerCanceled += OnPlayerCanceled;
InputManager.OnPlayerPerformed += OnPlayerPerformed;
lookAtIK = GetComponent<LookAtIK>();
lookTarget = new GameObject("SpineLookTarget").transform;
lookTarget.SetParent(_player.transform);
interactableLayer = LayerMask.GetMask("Interactive");
}
private void OnDestroy()
@@ -87,7 +105,7 @@ namespace NBF
{
firstPersonController.enabled = true;
}
private void Update()
{
var movementAxis = InputManager.GetMovementInput();
@@ -130,8 +148,11 @@ namespace NBF
nextShowSlotIndex = -1;
}
}
UpdatePlayerHandView();
}
private void FixedUpdate()
{
if (_player.MainArm)
@@ -139,5 +160,31 @@ namespace NBF
// _player.MainArm.Shoulder.SetCameraEulerAngleX(BaseCamera.Main.transform.localEulerAngles.x);
}
}
#region
private void UpdatePlayerHandView()
{
var cameraTransform = BaseCamera.Main.transform;
Vector3 cameraForward = cameraTransform.forward;
Vector3 flatForward = Vector3.ProjectOnPlane(cameraForward, Vector3.up).normalized;
// 获取相机 pitch 角度(负值是上看,正值是下看)
float pitchAngle = Vector3.SignedAngle(flatForward, cameraForward, cameraTransform.right);
// 限制 pitch 角度
pitchAngle = Mathf.Clamp(pitchAngle, -maxUpAngle, maxDownAngle);
// 重新构造限制后的目标方向
Quaternion limitedPitch = Quaternion.AngleAxis(pitchAngle, cameraTransform.right);
Vector3 limitedDirection = limitedPitch * flatForward;
// 设置目标点
lookTarget.position = cameraTransform.position + limitedDirection * aimDistance;
lookAtIK.solver.target = lookTarget;
}
#endregion
}
}

File diff suppressed because one or more lines are too long

View File

@@ -30,10 +30,10 @@ EditorUserSettings:
value: 550007565c005e0858575d23497a5c441516417d7a7171347c794931b6b1313c
flags: 0
RecentlyUsedSceneGuid-7:
value: 500606050702510d0e570876137a09441516197b782925632e2a4d64b3b16169
value: 515250075c0c595e5f5a5e71122159444e4e4a2f7a7d7f602f284d66b4b76661
flags: 0
RecentlyUsedSceneGuid-8:
value: 515250075c0c595e5f5a5e71122159444e4e4a2f7a7d7f602f284d66b4b76661
value: 500606050702510d0e570876137a09441516197b782925632e2a4d64b3b16169
flags: 0
RecentlyUsedSceneGuid-9:
value: 5505015f5c515a085f5b092149760f441716407a787d7564287b1b36e7e1366e