2026-03-15 점프,예비착지,착지후 경직
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using System.Threading;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerCharacterController : MonoBehaviour
|
||||
@@ -14,6 +15,8 @@ public class PlayerCharacterController : MonoBehaviour
|
||||
private Vector2 _moveInput; // 입력받은 이동 방향
|
||||
private Vector3 _velocityY = new Vector3(0,-2f,0); // 플레이어Y의 속도 //Y축만 물리법칙의 지배를 일부 받기 때문에 필요
|
||||
private Vector3 _moveTargetDir; // 실제 가고자하는 이동방향
|
||||
private float _moveCutTimer = 0f; //이동금지 타이머
|
||||
private Vector3 _rootMotionVelocity; //루트모션 사용시
|
||||
|
||||
//캐릭터 스피드
|
||||
[SerializeField] private float _spdCoefficient = 4f; //스피드 계수
|
||||
@@ -24,9 +27,11 @@ public class PlayerCharacterController : MonoBehaviour
|
||||
private float _currentSpd; //현재 스피드
|
||||
|
||||
//점프
|
||||
[SerializeField] private float _jumpPower = 1.5f; //점프 힘
|
||||
[SerializeField] private float _jumpPower = 3.0f; //점프 힘
|
||||
private float _jumpReadyCool = 0.8f; //점프 쿨타임
|
||||
private float _jumpReadyCoolTimer = 0f; //점프 쿨타이머
|
||||
private int _jumpCount = 0;
|
||||
private int _maxJumpCount = 2;
|
||||
|
||||
//대쉬
|
||||
[SerializeField] private AnimationCurve _dodgeCurve; // 변속용 커브
|
||||
@@ -75,13 +80,21 @@ private void Awake()
|
||||
PlayerCharacterStat = GetComponent<PlayerStat>();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_stateMachine.SetMaxJumpCount(_maxJumpCount);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
//캐릭터 컨트롤러는 FixedUpdate보다 Update에서 하는게 권장됨
|
||||
Movement();
|
||||
CheckGround();
|
||||
|
||||
StateUpdate();
|
||||
|
||||
Movement();
|
||||
WorkGravity();
|
||||
ApplyVelocity();
|
||||
ApplyMove();
|
||||
|
||||
TickTimer();
|
||||
//PlayerDebug();
|
||||
@@ -97,10 +110,66 @@ private void PlayerDebug()
|
||||
Debug.Log($"isGrounded : {_stateMachine.IsGrounded}");
|
||||
}
|
||||
|
||||
#region 상태 업데이트
|
||||
private void StateUpdate()
|
||||
{
|
||||
// 땅에서 추락할때
|
||||
if (!_stateMachine.IsGrounded && _velocityY.y < 0f && _stateMachine.CurrentState != PlayerState.Attack && _stateMachine.CurrentState != PlayerState.Charge)
|
||||
{
|
||||
_stateMachine.ChangeState(PlayerState.Fall);
|
||||
}
|
||||
//점프에서 바닥에 닿을때
|
||||
else if (_stateMachine.IsGrounded && _stateMachine.CurrentState == PlayerState.Fall)
|
||||
{
|
||||
_stateMachine.ChangeState(PlayerState.Idle);
|
||||
_moveCutTimer = 0.1f;
|
||||
}
|
||||
|
||||
if (_moveInput.sqrMagnitude < Mathf.Epsilon && _stateMachine.CanMove() && _stateMachine.CurrentState != PlayerState.Attack) // 지상 이동이 가능하고 공격중도 아닌데 이동입력이 없는상태 - 거의 0
|
||||
{
|
||||
_stateMachine.ChangeState(PlayerState.Idle);
|
||||
}
|
||||
else if(_stateMachine.CanMove() && _stateMachine.CurrentState != PlayerState.Attack) //지상이동이 가능하고 공격중이 아닌데 이동입력이 있다
|
||||
{
|
||||
// 런키를 누른 상태면 뛰는 상태, 아니면 걷는 상태
|
||||
_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
|
||||
_stateMachine.IsJumpCool = false;
|
||||
|
||||
|
||||
if(_stateMachine.IsGrounded)
|
||||
{
|
||||
_jumpCount = 0;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 체크
|
||||
private bool IsCloseToGround(float checkDistance)
|
||||
{
|
||||
return Physics.Raycast(transform.position, Vector3.down, checkDistance);
|
||||
}
|
||||
private void CheckGround()
|
||||
{
|
||||
_stateMachine.IsGrounded = _cController.isGrounded;
|
||||
_stateMachine.IsCloseToGround = IsCloseToGround(0.9f);
|
||||
|
||||
_anim.SetBool("IsGrounded", _stateMachine.IsGrounded);
|
||||
_anim.SetBool("IsCloseToGround", _stateMachine.IsCloseToGround);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -114,39 +183,10 @@ private void WorkGravity()
|
||||
|
||||
_velocityY.y += _gravityValue * Time.deltaTime;
|
||||
_anim.SetFloat("velocityY", _velocityY.y);
|
||||
_anim.SetBool("IsGrounded", _stateMachine.IsGrounded);
|
||||
|
||||
// 상태 자동 전환 로직
|
||||
if (!_stateMachine.IsGrounded && _stateMachine.CurrentState != PlayerState.Jump && _stateMachine.CurrentState != PlayerState.Attack && _stateMachine.CurrentState != PlayerState.Charge)
|
||||
{
|
||||
_stateMachine.ChangeState(PlayerState.Fall);
|
||||
}
|
||||
else if (_stateMachine.IsGrounded && _stateMachine.CurrentState == PlayerState.Fall)
|
||||
{
|
||||
_stateMachine.ChangeState(PlayerState.Idle);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 이동
|
||||
public void MoveInput(Vector2 moveInput)
|
||||
{
|
||||
if (_stateMachine.CanMove())
|
||||
{
|
||||
_moveInput = moveInput;
|
||||
}
|
||||
}
|
||||
public void SprintInput(InputState inputState)
|
||||
{
|
||||
if(inputState == InputState.Performing)
|
||||
{
|
||||
_stateMachine.IsRunInputPressed = true;
|
||||
}
|
||||
else if(inputState == InputState.Canceled)
|
||||
{
|
||||
_stateMachine.IsRunInputPressed = false;
|
||||
}
|
||||
}
|
||||
private void Movement()
|
||||
{
|
||||
//구르기중일때 전용 로직
|
||||
@@ -181,29 +221,11 @@ private void Movement()
|
||||
|
||||
float targetSpd = 0;
|
||||
|
||||
if (_moveInput.sqrMagnitude < Mathf.Epsilon) // 이동이 없는상태 - 거의 0
|
||||
if(_moveInput.sqrMagnitude > Mathf.Epsilon) //입력이 있다
|
||||
{
|
||||
targetSpd = 0f;
|
||||
// 완전히 멈추기 전까지는 이동 상태를 유지하다가 아주 느려지면 Idle 전환
|
||||
if (_currentSpd < 0.05f) _stateMachine.ChangeState(PlayerState.Idle);
|
||||
|
||||
|
||||
//가속도 안쓸시
|
||||
//_currentSpd = 0;
|
||||
//_stateMachine.ChangeState(PlayerState.Idle);
|
||||
}
|
||||
else //이동이 없지 않음 = 이동이 있다
|
||||
{
|
||||
// 런키를 누른 상태면 뛰는 스피드, 아니면 걷는 스피드 적용
|
||||
_stateMachine.ChangeState(_stateMachine.IsRunInputPressed ? PlayerState.Run : PlayerState.Walk);
|
||||
targetSpd = _stateMachine.IsRunInputPressed ? _runSpdRatio * _spdCoefficient : _walkSpdRatio * _spdCoefficient;
|
||||
|
||||
//가속도 안쓸시
|
||||
//_stateMachine.ChangeState(_stateMachine.IsRunInputPressed ? PlayerState.Run : PlayerState.Walk);
|
||||
//_currentSpd = _stateMachine.IsRunInputPressed ? _runSpdRatio * _spdCoefficient : _walkSpdRatio * _spdCoefficient;
|
||||
}
|
||||
|
||||
|
||||
// _currentSpd가 targetSpd로 서서히 접근
|
||||
float accelWeight = _stateMachine.CurrentState == PlayerState.Run ? 2 : 1; //런일때 가속도 가중치
|
||||
float currentStepSpeed = (targetSpd > _currentSpd) ? _acceleration : _deceleration;
|
||||
@@ -236,14 +258,81 @@ private void RotationByMove()
|
||||
#endregion
|
||||
|
||||
#region 속도적용
|
||||
private void ApplyVelocity()
|
||||
private void OnAnimatorMove()
|
||||
{
|
||||
// 애니메이션이 가고 싶은 값
|
||||
/*
|
||||
if(_stateMachine.CurrentState == PlayerState.Roll)
|
||||
{
|
||||
_rootMotionVelocity = _anim.deltaPosition / Time.deltaTime;
|
||||
}
|
||||
*/
|
||||
}
|
||||
private void ApplyMove()
|
||||
{
|
||||
//지상이동이 가능한 상황이 아니고, 공중이동도 가능한 상황이 아니라면
|
||||
if (!_stateMachine.CanMove() && !_stateMachine.CanControlInAir())
|
||||
{
|
||||
_moveTargetDir.x = 0f;
|
||||
_moveTargetDir.z = 0f;
|
||||
}
|
||||
|
||||
Vector3 finalVector = new Vector3(_moveTargetDir.x, _velocityY.y, _moveTargetDir.z);
|
||||
|
||||
_cController.Move(finalVector * Time.deltaTime); // xz 이동벡터를 적용
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 점프
|
||||
private void JumpAction()
|
||||
{
|
||||
_velocityY.y = Mathf.Sqrt(_jumpPower * -2f * _gravityValue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 대시(구르기,횡이동등)
|
||||
#region 타미어
|
||||
private void TickTimer()
|
||||
{
|
||||
if (_jumpReadyCoolTimer > 0) _jumpReadyCoolTimer -= Time.deltaTime; if (_jumpReadyCoolTimer < 0) _jumpReadyCoolTimer = 0f;
|
||||
if (_moveCutTimer > 0) _moveCutTimer -= Time.deltaTime; if (_moveCutTimer < 0) _moveCutTimer = 0f;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 입력
|
||||
public void MoveInput(Vector2 moveInput)
|
||||
{
|
||||
_moveInput = moveInput;
|
||||
}
|
||||
public void SprintInput(InputState inputState)
|
||||
{
|
||||
if (inputState == InputState.Performing)
|
||||
{
|
||||
_stateMachine.IsRunInputPressed = true;
|
||||
}
|
||||
else if (inputState == InputState.Canceled)
|
||||
{
|
||||
_stateMachine.IsRunInputPressed = false;
|
||||
}
|
||||
}
|
||||
public void JumpInput(InputState inputState)
|
||||
{
|
||||
if (_stateMachine.CanJump())
|
||||
{
|
||||
if (inputState == InputState.Started)
|
||||
{
|
||||
_anim.SetTrigger("jumpTrigger");
|
||||
_stateMachine.ChangeState(PlayerState.Jump);
|
||||
_jumpReadyCoolTimer = _jumpReadyCool;
|
||||
_ = Util.RunDelayed(0.1f, JumpAction, default);
|
||||
|
||||
_jumpCount++;
|
||||
_stateMachine.RecordJump();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
public void DodgeInput(InputState inputState)
|
||||
{
|
||||
// 구르기 가능한 상태일 때만
|
||||
@@ -262,31 +351,4 @@ public void DodgeInput(InputState inputState)
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 점프
|
||||
public void JumpInput(InputState inputState)
|
||||
{
|
||||
if(_stateMachine.CanJump())
|
||||
{
|
||||
if (inputState == InputState.Started && _stateMachine.IsGrounded && _stateMachine.CurrentState != PlayerState.Jump && _jumpReadyCoolTimer <= 0f)
|
||||
{
|
||||
_anim.SetTrigger("jumpTrigger");
|
||||
_stateMachine.ChangeState(PlayerState.Jump);
|
||||
_jumpReadyCoolTimer = _jumpReadyCool;
|
||||
_ = Util.RunDelayed(0.1f, JumpAction, default);
|
||||
}
|
||||
}
|
||||
}
|
||||
private void JumpAction()
|
||||
{
|
||||
_velocityY.y = Mathf.Sqrt(_jumpPower * -2f * _gravityValue);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region
|
||||
private void TickTimer()
|
||||
{
|
||||
if (_jumpReadyCoolTimer > 0) _jumpReadyCoolTimer -= Time.deltaTime; if (_jumpReadyCoolTimer < 0) _jumpReadyCoolTimer = 0f;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user