using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerStateMachine : StateMachine
{
public Player Player { get; }
// States
public PlayerIdleState IdleState { get; }
public PlayerWalkState WalkState { get; }
public PlayerRunState RunState { get; }
public PlayerJumpState JumpState { get; }
public PlayerFallState FallState { get; }
public PlayerComboAttackState ComboAttackState { get; }
//
public Vector2 MovementInput { get; set; }
public float MovementSpeed { get; private set; }
public float RotationDamping { get; private set; }
public float MovementSpeedModifier { get; set; } = 1f;
//
public bool IsAttacking { get; set; }
public int ComboIndex { get; set; }
public float JumpForce { get; set; }
public Transform MainCameraTransform { get; set; }
public PlayerStateMachine(Player player)
{
this.Player = player;
IdleState = new PlayerIdleState(this);
WalkState = new PlayerWalkState(this);
RunState = new PlayerRunState(this);
JumpState = new PlayerJumpState(this);
FallState = new PlayerFallState(this);
ComboAttackState = new PlayerComboAttackState(this);
MainCameraTransform = Camera.main.transform;
MovementSpeed = player.Data.GroundedData.BaseSpeed;
RotationDamping = player.Data.GroundedData.BaseRotationDamping;
}
}
가장 핵심이 되는 상태머신 스크립트에서 필요한 상태의 스크립트를 나열한다.
IdleState : 가장 기본이 되는 상태
WalkState : 걷고 있는 상태
RunState : 달리고 있는 상태
JumpState : 점프하고 있는 상태
FallState : 점프이후 혹은 낭떠러지에서 떨어지고 있는 상태
ComboAttackState : 공격 상태 (몇번째 콤보 상태인지까지 파악)
public interface IState
{
public void Enter();
public void Exit();
public void HandleInput();
public void Update();
public void PhysicsUpdate();
}
Enter : 상태에 진입할 때 호출할 것
Exit : 상태에서 나올 때 호출
HandleInput : 입력을 처리
허공이 아닌 땅 위에 있을때 진행될 상태를 여기서 전환.
점프를 누르자마자 전환
protected override void OnJumpStarted(InputAction.CallbackContext context)
{
stateMachine.ChangeState(stateMachine.JumpState);
}
이동키를 누르고 있다면 전환
protected virtual void OnMove()
{
stateMachine.ChangeState(stateMachine.WalkState);
}
공격키를 누르고 있다면 전환
protected virtual void OnAttack()
{
stateMachine.ChangeState(stateMachine.ComboAttackState);
}
protected override void OnMovementCanceled(InputAction.CallbackContext context)
{
if (stateMachine.MovementInput == Vector2.zero) //이동이 없을때
{
return;
}
stateMachine.ChangeState(stateMachine.IdleState);
base.OnMovementCanceled(context);
}
OnMovementCanceled는 애초에 Input이 끝났을때 처리하는 메소드이지만 Move Input 값은 안받고 있더라고 점프하거나 낭떠러지에서 떨어질때는 Idle로 전환하면 안되기 때문에 위와 같은 조건문 처리를 함
public override void PhysicsUpdate()
{
base.PhysicsUpdate();
//평소의 중력보다 값이 많을때 떨어지고 있다고 판단
if (!stateMachine.Player.Controller.isGrounded
&& stateMachine.Player.Controller.velocity.y < Physics.gravity.y * Time.fixedDeltaTime)
{
stateMachine.ChangeState(stateMachine.FallState);
return;
}
}
public override void Update()
{
base.Update();
//땅을 밟으면 멈추게
if (stateMachine.Player.Controller.isGrounded)
{
stateMachine.ChangeState(stateMachine.IdleState); //땅을 밟으면 Idle 상태로 전환
return;
}
}
이동 제어: 캐릭터를 전후좌우로 이동시키는 기능을 제공. 이동 방향과 속도를 조절하여 캐릭터를 이동.
중력 적용: 캐릭터에 중력을 적용하여 점프 후에 떨어지는 동작을 구현할 수 있다
충돌 처리: 캐릭터와 다른 물체 간의 충돌을 감지하고 처리. 이를 통해 벽이나 바닥과의 충돌을 감지하고, 이동을 방해하는 등의 작업을 수행.
지형 탐색: 캐릭터가 이동 가능한 지형과 접촉하는지를 확인. 이를 통해 캐릭터가 지형을 따라 이동하거나 경사를 오르내리는 등의 작업을 수행
애니메이션 제어: 일반적으로 CharacterController는 캐릭터의 실제 이동을 담당, 애니메이션은 이동 방향과 관련된 모션을 재생하는 데 사용
CharacterController > Collider
CharacterController < RigidBady
카메라 시스템을 강화하기 위한 패키지 중 하나이다.
PlayerStateMachine에서 public Player Player { get; }데이터를 초기화 해서 가능하게 된것 같긴한데 아무리 생각해도 여러가지 스크립트의 Update 문이나 Exit문 등, 오브젝트에 달려 있지도 않은데 돌아가는 이유를 잘 모르겠으며, 내가 지금 뭘 몰라서 모르고 있는지도 모르겠으니 튜터님한테 꼭 이 점 물어보기
//땅을 밟으면 멈추게
if (stateMachine.Player.Controller.isGrounded)
{
stateMachine.ChangeState(stateMachine.IdleState); //땅을 밟으면 Idle 상태로 전환
return;
}
CharacterController는 sGrounded 라는 bool 값이 있는데 얘가 충돌한 것이 그라운드인지 아니면 단순한 오브젝트인지 어떻게 판별하는걸까? 그냥 아래쪽에 충돌하는 것을 Ground 라고 판별하는건가?