2026-03-17 14:19 FPS시점의 Strafe캐릭터 조작과 에임모드 전환
This commit is contained in:
@@ -5,8 +5,6 @@
|
||||
|
||||
public class AimCameraRig : CameraRigBase
|
||||
{
|
||||
public InputAxis AimMode = InputAxis.DefaultMomentary; //누르는 동안만 유지
|
||||
|
||||
[SerializeField] private CinemachineCamera _aimCamera;
|
||||
[SerializeField] private CinemachineCamera _freeCamera;
|
||||
|
||||
@@ -16,7 +14,7 @@ public class AimCameraRig : CameraRigBase
|
||||
|
||||
public CinemachineCamera ActiveCmCamera => LiveChild as CinemachineCamera;
|
||||
|
||||
private bool _isAiming => AimMode.Value > 0.5f;
|
||||
private bool _isAiming => _controller != null && _controller.IsAiming;
|
||||
private float _lastKnownFOV = 60f;
|
||||
|
||||
protected override void Awake()
|
||||
@@ -55,7 +53,6 @@ protected override void Start()
|
||||
public override void GetInputAxes(List<IInputAxisOwner.AxisDescriptor> axes)
|
||||
{
|
||||
base.GetInputAxes(axes);
|
||||
axes.Add(new() { DrivenAxis = () => ref AimMode, Name = "Aim" });
|
||||
}
|
||||
|
||||
protected override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worldUp, float deltaTime)
|
||||
@@ -63,10 +60,17 @@ protected override CinemachineVirtualCameraBase ChooseCurrentCamera(Vector3 worl
|
||||
var oldCam = (CinemachineVirtualCameraBase)LiveChild;
|
||||
var newCam = _isAiming ? _aimCamera : _freeCamera;
|
||||
if (_controller != null && oldCam != newCam)
|
||||
{
|
||||
_controller.RotationMode = _isAiming
|
||||
? PlayerCharacterController.PlayerRotationMode.CameraCoupled
|
||||
: PlayerCharacterController.PlayerRotationMode.CameraDecoupled;
|
||||
{
|
||||
//에임모드에서 다시 돌아갈때 플레이어의 현재 회전값에 카메라를 일치시킴
|
||||
if(newCam == _freeCamera)
|
||||
{
|
||||
CinemachineOrbitalFollow orbitalFollow = newCam.GetComponent<CinemachineOrbitalFollow>();
|
||||
|
||||
orbitalFollow.HorizontalAxis.Recentering.Enabled = true;
|
||||
orbitalFollow.VerticalAxis.Recentering.Enabled = true;
|
||||
orbitalFollow.HorizontalAxis.Recentering.Enabled = false;
|
||||
orbitalFollow.VerticalAxis.Recentering.Enabled = false;
|
||||
}
|
||||
_controller.RecenterPlayer();
|
||||
}
|
||||
return newCam;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
public abstract class CameraRigBase : CinemachineCameraManagerBase, IInputAxisOwner
|
||||
{
|
||||
protected PlayerCharacterController _controller;
|
||||
|
||||
protected abstract IReadOnlyList<CinemachineVirtualCameraBase> CameraCandidates { get; }
|
||||
public CinemachineCamera LiveCmCamera => LiveChild as CinemachineCamera;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
|
||||
@@ -2,13 +2,16 @@
|
||||
using System.Threading;
|
||||
using Unity.Cinemachine;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine;
|
||||
using static Unity.Cinemachine.CinemachineSplineDolly;
|
||||
using static UnityEngine.Rendering.DebugUI;
|
||||
|
||||
public class PlayerCharacterController : MonoBehaviour
|
||||
{
|
||||
private CharacterController _cController;
|
||||
private Animator _anim;
|
||||
|
||||
private PlayerStateMachine _stateMachine;
|
||||
|
||||
//환경
|
||||
@@ -44,16 +47,25 @@ public class PlayerCharacterController : MonoBehaviour
|
||||
private Vector3 _dodgeDir; // 대쉬 시작 시점의 방향 고정
|
||||
|
||||
//카메라 전환
|
||||
[SerializeField] private AimCameraRig _aimCameraRig; //조준 카메라 집합체
|
||||
private CameraMode _cameraMode = CameraMode.FreeLook; //카메라 모드
|
||||
private CancellationTokenSource _cameraDelayChangeCts; //지연전환 취소 토큰
|
||||
public enum PlayerRotationMode {CameraCoupled, CameraDecoupled}
|
||||
public PlayerRotationMode RotationMode = PlayerRotationMode.CameraCoupled;
|
||||
|
||||
//일단은 기본값
|
||||
|
||||
//조준모드용 세팅
|
||||
[Header("AimMode Rotation Settings")]
|
||||
private Vector2 _lookInput;
|
||||
private float _lookPitch = 0f;
|
||||
[SerializeField] private float _lookSensitivity = 0.1f;
|
||||
[SerializeField] private float _upperLookLimit = 80f; // 위로 보기 제한
|
||||
[SerializeField] private float _lowerLookLimit = -80f; // 아래로 보기 제한
|
||||
|
||||
|
||||
//게걸음 이동
|
||||
public bool Strafe = false;
|
||||
public void SetStrafeMode(bool b) => Strafe = b;
|
||||
|
||||
//조준모드
|
||||
public bool IsAiming => _stateMachine != null && _stateMachine.IsAiming;
|
||||
|
||||
//캐릭터 관련
|
||||
public CharacterIdentity PlayerCharacterIdentity { get; set; }
|
||||
@@ -93,6 +105,7 @@ private void Awake()
|
||||
private void Start()
|
||||
{
|
||||
_stateMachine.SetMaxJumpCount(_maxJumpCount);
|
||||
SetCursorLockState(true);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
@@ -145,16 +158,11 @@ private void StateUpdate()
|
||||
_stateMachine.ChangeState(_stateMachine.IsRunInputPressed ? PlayerState.Run : PlayerState.Walk);
|
||||
}
|
||||
|
||||
Debug.Log($"_moveCutTimer : {_moveCutTimer}");
|
||||
|
||||
if (_moveCutTimer > 0)
|
||||
_stateMachine.IsMoveCut = true;
|
||||
else
|
||||
_stateMachine.IsMoveCut = false;
|
||||
|
||||
Debug.Log($"_moveCut : {_stateMachine.IsMoveCut}");
|
||||
Debug.Log($"CurentState : {_stateMachine.CurrentState}");
|
||||
|
||||
if (_jumpReadyCoolTimer > 0)
|
||||
_stateMachine.IsJumpCool = true;
|
||||
else
|
||||
@@ -209,7 +217,7 @@ private void Movement()
|
||||
if (normalizedTime >= 1.0f)
|
||||
{
|
||||
// 구르기 종료 -> 원래상태로 복귀 로직
|
||||
//_stateMachine.ChangeState(PlayerState.Idle);
|
||||
//StateMachine.ChangeState(PlayerState.Idle);
|
||||
//_currentSpd = 0f;
|
||||
|
||||
return;
|
||||
@@ -260,8 +268,6 @@ private void Movement()
|
||||
//방향키 방향으로 회전하며 이동
|
||||
//RotationByMove();
|
||||
|
||||
Debug.Log($"Forward : {camForward}");
|
||||
|
||||
//모드별 회전
|
||||
RotationByMode();
|
||||
_anim.SetFloat("DirectX", moveDir.x * _currentSpd / _spdCoefficient);
|
||||
@@ -278,19 +284,40 @@ private void RotationByMove()
|
||||
}
|
||||
private void RotationByMode()
|
||||
{
|
||||
switch (RotationMode)
|
||||
if (IsAiming) //조준 모드일때는 마우스가 캐릭터 자체를 회전시키고 카메라가 따라간다 (Third Person Follow)
|
||||
{
|
||||
case PlayerRotationMode.CameraCoupled:
|
||||
{
|
||||
SetStrafeMode(true);
|
||||
RecenterPlayer();
|
||||
break;
|
||||
}
|
||||
case PlayerRotationMode.CameraDecoupled:
|
||||
{
|
||||
SetStrafeMode(false);
|
||||
break;
|
||||
}
|
||||
// 좌우 회전 (Yaw): 캐릭터 본체를 직접 회전시킴
|
||||
float yaw = _lookInput.x * _lookSensitivity;
|
||||
transform.Rotate(Vector3.up * yaw);
|
||||
|
||||
// 상하 회전 (Pitch): 캐릭터는 그대로 두고 내부 변수만 계산
|
||||
_lookPitch -= _lookInput.y * _lookSensitivity;
|
||||
_lookPitch = Mathf.Clamp(_lookPitch, _lowerLookLimit, _upperLookLimit);
|
||||
|
||||
CinemachineCamera liveCm = GameManager.Instance.Camera.GetLiveCinemachineCamera();
|
||||
|
||||
if(liveCm != null)
|
||||
{
|
||||
Transform lookTarget = liveCm.LookAt;
|
||||
lookTarget.localRotation = Quaternion.Euler(_lookPitch, 0, 0);
|
||||
}
|
||||
}
|
||||
else //조준 모드가 아니면 회전모드를 따라간다
|
||||
{
|
||||
switch (RotationMode)
|
||||
{
|
||||
case PlayerRotationMode.CameraCoupled:
|
||||
{
|
||||
SetStrafeMode(true);
|
||||
RecenterPlayer();
|
||||
break;
|
||||
}
|
||||
case PlayerRotationMode.CameraDecoupled:
|
||||
{
|
||||
SetStrafeMode(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +342,7 @@ private void OnAnimatorMove()
|
||||
{
|
||||
// 애니메이션이 가고 싶은 값
|
||||
/*
|
||||
if(_stateMachine.CurrentState == PlayerState.Roll)
|
||||
if(StateMachine.CurrentState == PlayerState.Roll)
|
||||
{
|
||||
_rootMotionVelocity = _anim.deltaPosition / Time.deltaTime;
|
||||
}
|
||||
@@ -403,5 +430,34 @@ public void DodgeInput(InputState inputState)
|
||||
_dodgeTimer = 0f;
|
||||
}
|
||||
}
|
||||
public void AimToggleInput(InputState inputState)
|
||||
{
|
||||
if (inputState == InputState.Started)
|
||||
{
|
||||
if (_stateMachine.IsAiming)
|
||||
{
|
||||
_stateMachine.IsAiming = false;
|
||||
GameManager.Instance.InGameUI.VisibleCrossHair(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_stateMachine.IsAiming = true;
|
||||
GameManager.Instance.InGameUI.VisibleCrossHair(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void LookInput(Vector2 lookInput)
|
||||
{
|
||||
_lookInput = lookInput;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 헬퍼
|
||||
public void SetCursorLockState(bool isLocked)
|
||||
{
|
||||
Cursor.lockState = isLocked ? CursorLockMode.Locked : CursorLockMode.None;
|
||||
Cursor.visible = !isLocked;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ public class PlayerStateMachine : MonoBehaviour
|
||||
public bool IsPossibleCharge { get; set; } //현재 차지 가능한 상태인가
|
||||
public bool IsMoveCut { get; set; } //현재 이동 금지 상태인가
|
||||
public bool IsJumpCool { get; set; } //현재 점프 쿨타임 상태인가
|
||||
public bool IsAiming { get; set; } // 현재 aim모드인가
|
||||
|
||||
private int _jumpCount = 0;
|
||||
private int _maxJumpCount = 1;
|
||||
|
||||
Reference in New Issue
Block a user