캐릭터 움직임 및 애니메이션
This commit is contained in:
234
Assets/Scripts/Player/PlayerMovement.cs
Normal file
234
Assets/Scripts/Player/PlayerMovement.cs
Normal file
@@ -0,0 +1,234 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using Unity.Netcode;
|
||||
using Colosseum.Network;
|
||||
|
||||
namespace Colosseum.Player
|
||||
{
|
||||
/// <summary>
|
||||
/// 3인칭 플레이어 이동 (네트워크 동기화)
|
||||
/// </summary>
|
||||
[RequireComponent(typeof(CharacterController))]
|
||||
public class PlayerMovement : NetworkBehaviour
|
||||
{
|
||||
[Header("Movement Settings")]
|
||||
[SerializeField] private float moveSpeed = 5f;
|
||||
[SerializeField] private float rotationSpeed = 10f;
|
||||
[SerializeField] private float gravity = -9.81f;
|
||||
|
||||
[Header("Jump Settings")]
|
||||
[SerializeField] private float jumpForce = 5f;
|
||||
|
||||
private CharacterController characterController;
|
||||
private Vector3 velocity;
|
||||
private Vector2 moveInput;
|
||||
private InputSystem_Actions inputActions;
|
||||
private bool isJumping;
|
||||
private bool wasGrounded;
|
||||
|
||||
/// <summary>
|
||||
/// 현재 이동 속도 (애니메이션용)
|
||||
/// </summary>
|
||||
public float CurrentMoveSpeed => moveInput.magnitude * moveSpeed;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 현재 지면 접촉 상태
|
||||
/// </summary>
|
||||
public bool IsGrounded => characterController != null ? characterController.isGrounded : false;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 점프 중 상태
|
||||
/// </summary>
|
||||
public bool IsJumping => isJumping;
|
||||
|
||||
public override void OnNetworkSpawn()
|
||||
{
|
||||
// 로컬 플레이어가 아니면 입력 비활성화
|
||||
if (!IsOwner)
|
||||
{
|
||||
enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
characterController = GetComponent<CharacterController>();
|
||||
|
||||
// 스폰 포인트에서 위치 설정
|
||||
SetSpawnPosition();
|
||||
|
||||
// Input Actions 초기화
|
||||
inputActions = new InputSystem_Actions();
|
||||
inputActions.Player.Enable();
|
||||
|
||||
// Move 액션 콜백 등록
|
||||
inputActions.Player.Move.performed += OnMovePerformed;
|
||||
inputActions.Player.Move.canceled += OnMoveCanceled;
|
||||
|
||||
// Jump 액션 콜백 등록
|
||||
inputActions.Player.Jump.performed += OnJumpPerformed;
|
||||
|
||||
// 카메라 설정
|
||||
SetupCamera();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 스폰 위치 설정
|
||||
/// </summary>
|
||||
private void SetSpawnPosition()
|
||||
{
|
||||
Transform spawnPoint = PlayerSpawnPoint.GetRandomSpawnPoint();
|
||||
|
||||
if (spawnPoint != null)
|
||||
{
|
||||
// CharacterController 비활성화 후 위치 설정 (충돌 문제 방지)
|
||||
characterController.enabled = false;
|
||||
transform.position = spawnPoint.position;
|
||||
transform.rotation = spawnPoint.rotation;
|
||||
characterController.enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 네트워크 정리리
|
||||
/// </summary>
|
||||
public override void OnNetworkDespawn()
|
||||
{
|
||||
if (inputActions != null)
|
||||
{
|
||||
inputActions.Player.Move.performed -= OnMovePerformed;
|
||||
inputActions.Player.Move.canceled -= OnMoveCanceled;
|
||||
inputActions.Player.Jump.performed -= OnJumpPerformed;
|
||||
inputActions.Disable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnMovePerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
moveInput = context.ReadValue<Vector2>();
|
||||
}
|
||||
|
||||
|
||||
private void OnMoveCanceled(InputAction.CallbackContext context)
|
||||
{
|
||||
moveInput = Vector2.zero;
|
||||
}
|
||||
|
||||
|
||||
private void OnJumpPerformed(InputAction.CallbackContext context)
|
||||
{
|
||||
if (!isJumping && characterController.isGrounded)
|
||||
{
|
||||
Jump();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void SetupCamera()
|
||||
{
|
||||
var cameraController = GetComponent<PlayerCamera>();
|
||||
if (cameraController == null)
|
||||
{
|
||||
cameraController = gameObject.AddComponent<PlayerCamera>();
|
||||
}
|
||||
cameraController.Initialize(transform, inputActions);
|
||||
}
|
||||
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!IsOwner) return;
|
||||
|
||||
ApplyGravity();
|
||||
Move();
|
||||
}
|
||||
|
||||
|
||||
private void ApplyGravity()
|
||||
{
|
||||
if (wasGrounded && velocity.y < 0)
|
||||
{
|
||||
velocity.y = -2f;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.y += gravity * Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Move()
|
||||
{
|
||||
if (characterController == null) return;
|
||||
|
||||
// 이동 방향 계산 (카메라 기준)
|
||||
Vector3 moveDirection = new Vector3(moveInput.x, 0f, moveInput.y);
|
||||
moveDirection = TransformDirectionByCamera(moveDirection);
|
||||
moveDirection.Normalize();
|
||||
|
||||
// 이동 적용
|
||||
Vector3 moveVector = moveDirection * moveSpeed * Time.deltaTime;
|
||||
characterController.Move(moveVector + velocity * Time.deltaTime);
|
||||
|
||||
// 회전 (이동 중일 때만)
|
||||
if (moveDirection != Vector3.zero)
|
||||
{
|
||||
Quaternion targetRotation = Quaternion.LookRotation(moveDirection);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
|
||||
}
|
||||
|
||||
// 착지 체크 (Move 후에 isGrounded가 업데이트됨)
|
||||
if (!wasGrounded && characterController.isGrounded && isJumping)
|
||||
{
|
||||
OnJumpEnd();
|
||||
}
|
||||
|
||||
// 다음 프레임을 위해 현재 상태 저장
|
||||
wasGrounded = characterController.isGrounded;
|
||||
}
|
||||
|
||||
|
||||
private void Jump()
|
||||
{
|
||||
isJumping = true;
|
||||
velocity.y = jumpForce;
|
||||
|
||||
// 애니메이션 컨트롤러에 점프 알림
|
||||
var animController = GetComponent<PlayerAnimationController>();
|
||||
if (animController != null)
|
||||
{
|
||||
animController.PlayJump();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 점프 중 상태가 끝나면 IsJumping = false;
|
||||
/// </summary>
|
||||
public void OnJumpEnd()
|
||||
{
|
||||
isJumping = false;
|
||||
}
|
||||
|
||||
|
||||
private Vector3 TransformDirectionByCamera(Vector3 direction)
|
||||
{
|
||||
if (Camera.main == null) return direction;
|
||||
|
||||
Transform cameraTransform = Camera.main.transform;
|
||||
Vector3 cameraForward = cameraTransform.forward;
|
||||
Vector3 cameraRight = cameraTransform.right;
|
||||
|
||||
// Y축 제거
|
||||
cameraForward.y = 0f;
|
||||
cameraRight.y = 0f;
|
||||
cameraForward.Normalize();
|
||||
cameraRight.Normalize();
|
||||
|
||||
return cameraRight * direction.x + cameraForward * direction.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user