2024. 1. 24. 21:09ㆍ카테고리 없음
1. Player 관련해서 에쎗이 갑자기 사라져서 새로 에쎗을 추가했다.
2. Player Input 컴포넌트에 Invoke Unity Events 의 연결을 추가했다.
3. 플레이어 애니메이션을 추가했다. FSM 방식으로 애니메이션을 초기에 설정을 했었는데, 이번에는 Character Controller 사용대신 Rigidbody 와 Collider 를 사용한 플레이어를 만들어서 새로운 애니메이션 컨트롤러를 생성했다.
bool 파라미터를 사용하여 애니메이션 트랜지션을 연결해주었고, PlayerController 스크립트에 애니메이션 컴포넌트와, 실행함수를 추가해주었다.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using UnityEditor.Build;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private Animator animator; //애니메이터 추가
public float baseSpeed = 5f; //기본 속도
public float currentSpeed; //현재 속도
[Header("Movement")]
public float moveSpeed;
private Vector2 curMovementInput;
public float jumpForce;
public LayerMask groundLayerMask;
[Header("Look")]
public Transform cameraContainer;
public float minXLook;
public float maxXLook;
private float camCurXRot;
public float lookSensitivity;
private Vector2 mouseDelta;
[HideInInspector]
public bool canLook = true;
private Rigidbody _rigidbody;
public static PlayerController instance;
private void Awake()
{
instance = this;
_rigidbody = GetComponent<Rigidbody>();
animator = GetComponent<Animator>(); //애니메이터 컴포넌트 추가
}
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
currentSpeed = baseSpeed; //속도
}
public void ApplySpeedPotion(float SpeedUp) //속도
{
currentSpeed += SpeedUp;
}
public void ResetSpeed() //속도
{
currentSpeed = baseSpeed;
}
private void FixedUpdate()
{
Move();
}
private void LateUpdate()
{
if (canLook)
{
CameraLook();
}
}
private void Move()
{
Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
dir *= moveSpeed;
dir.y = _rigidbody.velocity.y;
_rigidbody.velocity = dir;
}
void CameraLook()
{
camCurXRot += mouseDelta.y * lookSensitivity;
camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook);
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
}
public void OnLookInput(InputAction.CallbackContext context)
{
mouseDelta = context.ReadValue<Vector2>();
}
public void OnMoveInput(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Performed)
{
curMovementInput = context.ReadValue<Vector2>();
animator.SetBool("Walk", true); //MoveInput이 실행될 때 Walk 애니메이션의 bool을 true로 바꾼다.
}
else if (context.phase == InputActionPhase.Canceled)
{
curMovementInput = Vector2.zero;
animator.SetBool("Walk", false);
}
}
public void OnJumpInput(InputAction.CallbackContext context)
{
if (context.phase == InputActionPhase.Started)
{
if (IsGrounded())
_rigidbody.AddForce(Vector2.up * jumpForce, ForceMode.Impulse);
}
}
private bool IsGrounded()
{
Ray[] rays = new Ray[4]
{
new Ray(transform.position + (transform.forward * 0.2f) + (Vector3.up * 0.01f) , Vector3.down),
new Ray(transform.position + (-transform.forward * 0.2f)+ (Vector3.up * 0.01f), Vector3.down),
new Ray(transform.position + (transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
new Ray(transform.position + (-transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
};
for (int i = 0; i < rays.Length; i++)
{
if (Physics.Raycast(rays[i], 0.1f, groundLayerMask))
{
return true;
}
}
return false;
}
private void OnDrawGizmos()
{
Gizmos.color = Color.red;
Gizmos.DrawRay(transform.position + (transform.forward * 0.2f), Vector3.down);
Gizmos.DrawRay(transform.position + (-transform.forward * 0.2f), Vector3.down);
Gizmos.DrawRay(transform.position + (transform.right * 0.2f), Vector3.down);
Gizmos.DrawRay(transform.position + (-transform.right * 0.2f), Vector3.down);
}
public void ToggleCursor(bool toggle)
{
Cursor.lockState = toggle ? CursorLockMode.None : CursorLockMode.Locked;
canLook = !toggle;
}
}
전투나, 장애물 넘는 과정에서 FSM 방식으로 애니메이션을 기획하면 연계되는 게 더욱 깔끔한 것 같은데, 아직 이해를 완전히 하지 못해서 응용하는 부분에서 애로사항을 겪는 것 같다.
FSM 방식에서는 Player 오브젝트의 하위 prefabs 모델에 있는 캐릭터에 애니메이터를 적용해주었는데, 새로 만든 NewPlayer의 경우 Animator 컴포넌트를 NewPlayer 오브젝트 자체에 적용을 해준 뒤 Avatar를 추가해서 애니메이션을 만들었다.
다양한 방법들이 있겠지만 아직까지 활용하는 부분은 어렵게만 느껴진다.
애자일 방식으로 게임의 한 싸이클을 진행하기 위한 준비는 거의 끝나가는 것 같다.
몬스터 or 적을 구현하여 플레이어를 따라오게 하는 Chasing 부분만 잘 해결하면 기획했던 내용들은 어느정도 갖췄다고 생각한다.
24일 수요일에 기술면접도 진행을 해보았는데, 머리속에 있는 내용들을 말로써 논리정연하게 설명하는 것이 수월하지 않는 걸 보니 아직 이론에 대한 내용들도 정리가 더 된 것 같다.
면접에서 꼬리질문으로 계속해서 질문이 이어졌는데, struct vs class 에 대한 차이를 설명하고 -> 값형식 vs 참조형식 -> 스택방식 vs 힙방식 -> 가비지컬렉터로 이어졌다.
세부적인 내용까지 잘 이해하기 위해서 더욱 공부를 해야겠다.