플레이어 동작 시스템
전체 플레이 영상
전체 코드
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public static PlayerController instance;
// 외부 참조
PlayerManager playerManager;
PlayerSkillController skillController;
[Header("카메라 위치")]
[SerializeField] private Transform camPos;
private Camera mainCam;
private CharacterController cc;
[HideInInspector] public Animator anim;
[Header("이동 설정")]
float walkSpeed = 0.0f;
float runSpeed = 0.0f;
public float jumpForce = 10.0f;
public float gravity = 10.0f; // +하면 위로, -하면 아래로 하기 위해서 (점프)
float yVelocity = 0; // 점프를 위해서
// 상태
public bool isInvincibility = false;
// 애니메이터 해시
static class AnimHash
{
public static readonly int Walk = Animator.StringToHash("Walk");
public static readonly int Run = Animator.StringToHash("Run");
public static readonly int Jump = Animator.StringToHash("Jump");
public static readonly int Die = Animator.StringToHash("Die");
public static readonly int Hit = Animator.StringToHash("hit");
}
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
return;
}
cc = GetComponent<CharacterController>();
anim = GetComponent<Animator>();
}
private void Start()
{
playerManager = PlayerManager.instance;
skillController = GetComponent<PlayerSkillController>();
mainCam = Camera.main;
}
private void LateUpdate()
{
if (mainCam == null || !mainCam)
mainCam = Camera.main;
// 카메라 위치 및 방향 동기화
if (mainCam && camPos)
{
mainCam.transform.position = camPos.position;
transform.rotation = mainCam.transform.rotation;
}
}
private void Update()
{
if (anim.GetBool(AnimHash.Die)) return;
HandleMovement();
skillController.HandleSkill();
CheckDeath();
}
void CheckDeath()
{
if (playerManager.CurrentHp <= 0 && !anim.GetBool(AnimHash.Die) && !isInvincibility)
{
anim.SetBool(AnimHash.Die, true);
UI_Manager.instance.respawnUI.SetActive(true);
}
}
void HandleMovement()
{
HandleJump();
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
// 1) 입력 → 로컬 → 월드 (수평 성분만)
Vector3 inputDir = new Vector3(x, 0f, z);
Vector3 planarDir = transform.TransformDirection(inputDir).normalized;
// 2) 속도 선택
walkSpeed = playerManager.PlayerStatus.MoveSpeed;
runSpeed = playerManager.PlayerStatus.RunSpeed;
bool isRunning = Input.GetKey(KeyCode.LeftShift);
float speed = (x != 0 || z != 0) ? (isRunning ? runSpeed : walkSpeed) : 0f;
// 3) 애니메이션
anim.SetBool(AnimHash.Walk, speed > 0f && !isRunning);
anim.SetBool(AnimHash.Run, speed > 0f && isRunning);
// 4) 중력 갱신 (아래로 가속)
yVelocity -= gravity * Time.deltaTime;
// 5) ***수평과 수직을 분리해서 합산***
Vector3 velocity = planarDir * speed; // 수평 속도
velocity.y = yVelocity; // 수직 속도 (speed로 곱하지 않음)
// 6) 최종 이동 (프레임당 한 번만)
cc.Move(velocity * Time.deltaTime);
}
void HandleJump()
{
if (cc.isGrounded)
{
// 접지 시 살짝 붙여주기(경계에서 붕뜸 방지)
if (yVelocity < 0f) yVelocity = -2f;
if (Input.GetKey(KeyCode.Space))
{
yVelocity = jumpForce;
anim.SetBool(AnimHash.Jump, true);
}
else if (anim.GetBool(AnimHash.Jump))
{
anim.SetBool(AnimHash.Jump, false);
}
}
}
public void Damage()
{
anim.SetTrigger(AnimHash.Hit);
}
}
using UnityEngine;
public class Camera_ : MonoBehaviour
{
private static Camera_ instance;
SettingManager settingManager;
MonsterTargeting monsterTargeting;
public float rotationSpeed = 50f; // 카메라 회전 속도
float rotationX = 0.0f; // 카메라의 수직 회전 각도
float rotationY = 0.0f; // 카메라의 수평 회전 각도
GameObject targetMonster; // 타겟 몬스터
private void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else if (instance != this)
{
Destroy(gameObject);
}
}
private void Start()
{
settingManager = SettingManager.instance;
monsterTargeting = GameObject.Find("Player").GetComponent<MonsterTargeting>();
}
void Update()
{
rotationSpeed = settingManager.MouseSensitivity(); // 마우스 감도 설정 가져오기
CameraRotation();
LookAtTargetMonster();
}
// 카메라 회전 처리
void CameraRotation()
{
if (Input.GetMouseButton(1))
{
float mouseX = Input.GetAxis("Mouse X"); // 수평 움직임
float mouseY = Input.GetAxis("Mouse Y"); // 수직 움직임
rotationX += mouseX * rotationSpeed * Time.deltaTime; // 수평 회전량 계산
rotationY += mouseY * rotationSpeed * Time.deltaTime; // 수직 회전량 계산
// 수직 회전 각도를 제한하여 너무 위나 아래로 카메라가 회전하지 않도록 함
if (rotationY < -15) rotationY = -15;
else if (rotationY > 15) rotationY = 15;
transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0); // 카메라의 로컬 각도를 설정하여 회전 적용
}
}
// 타겟 몬스터를 바라보게 처리
void LookAtTargetMonster()
{
if (monsterTargeting != null)
{
targetMonster = monsterTargeting.TargetMonster; // 타겟 몬스터 가져옴
if (targetMonster != null)
{
Vector3 targetPosition = targetMonster.transform.position; // 타겟 몬스터의 위치
targetPosition.y = transform.position.y; // 카메라의 높이에 맞게 y값 설정
// 타겟 몬스터를 바라보는 방향 계산
Quaternion targetRotation = Quaternion.LookRotation(targetPosition - transform.position);
// 부드러운 회전을 위해 Slerp를 사용하여 카메라 회전 적용
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
}
}
}
}
