본문 바로가기
제출용/TIL

내일배움캠프 31일차 TIL + 플레이어 만들기

by 유린테 2024. 5. 30.

플레이어 만들기

 

먼저 하이어라키뷰에 빈 오브젝트로 플레이어를 만들고 그 안에 카메라콘테이너를 만든 후

기존에 있던 메인카메라를 그 안으로 넣어준다.

 

그 후 Player에 캡슐콜라이더를 넣어주는데

이제 3D니까 2D가 아니라 그냥 캡슐콜라이더를 넣어준다!!!!!! 

 

그리고 물건 생성했을 때 바닥이 아니라 공중에 떠있었는데, 씬에 Pivot이 아니라 Center가 되어 있어 그런거였다.

설정을 Pivot  으로 바꿔주고, 캡슐 콜라이더를 사람크기로 바꿔주었다.

 

그리고 리기드바디도 이번에도 2D가 아닌 그냥 리기드바디!!!!!

Mass 로 무게를 20정도로 조정해주고,

Constraints 에서 돌아가지 않도록 로테이션을 XYZ 모두 freeze 해준다.

 

 

키보드 인풋값 설정해주기

- 플레이어 움직이기

 

프로젝트뷰에 InputActions 폴더를 만들어준다

Window 에서 PackageManger에서 인풋시스템패키지 설치해줌

Unity Registry로 해놓고 input system 찾아서 install 해주면 됨

>> 설치하고 나면 restart 뜨는데 그냥 ok 눌러서 재시작 해주면 됨

 

그리고 만들어놓은 InputActions 폴더에 

create - inputActions 해서 인풋액션 생성해주고, 이름을 PlayerInput 으로 변경해줌

 

인스펙터창에서 Edit Asset 누르면 키 설정 창이 뜬다

 

<캐릭터 움직이기 - wasd>

ActionMap 만들어주기 - Actions 에 Move 만들어주기

캐릭터 움직이는건 Vector2 니까 Value - Vector2 해 주기

Move 옆 + 누르면 업다운레프트라이트 있는거 눌러서 WSAD 하나씩 지정해주기

 

<캐릭터 마우스 따라 방향 돌리기 - 마우스>

Actions에 Look 만들어주고 얘는 Value- Delta로 만들어주고 바인딩 path 에서 Mouse-Delta 해줌!

 

 

<Jump - 스페이스바>

점프는 버튼 한번 누르면 되니까  button! 

바인딩에서 space로 지정해주면 스페이스바 !

근데 바인딩 할 때 좌클릭 안돼고 우클릭으로 해야하는거 자꾸 까먹고 흠칫함

 

<인벤토리 열기 - tab>

이것도 한번 눌러주면 되는거니 button - 키보드에 Tab키로 등록

 

<파밍 - e >

파밍 (템줍기)는 E키

이것도 한번 누르면 되는거니까 button - 키보드 e 세팅해주기

 

<공격 - 마우스 왼쪽>

공격도 마우스 한번 딸깍이니까 button- LeftMouse 해주기!

 

이렇게 해주면 키세팅 악보가 완성된다

 

그리고 창 닫기 전에 맨 윗쪽 중간의  SaveAsset 필수!!!!!!!!!!!!!

 

 

그리고나서 Player 에 PlayerInput 컴포넌트를 붙여주고

Actions에 만든 PlayerInput을 붙여주면 된다!

그리고 원래는 Behavior를 SendMessage 로 사용했는데, 이번엔 Invoke Unity Events 로 사용한다.

SendMessage는 OnMove 같은 함수를 알아서 찾아주는 모드였음

 

Invoke Unity Events 를 눌러주면 밑에 Event가 생기는데

이렇게 아까 만들어준 Input 키들이 있다.

스크립트 작성해서 넣어주면 될듯!

 

그리고 인스펙터창에서 Player 라는 레이어를 하나 만들어줌

Layer- AddLayer 하면 됨

그리고 Player 게임 오브젝트 레이어를 Player 레이어로 바꿔주고, 칠드런까지 다 같이 바꿔준다.

 

Scripts 폴더 만들고 캐릭터매니저, 플레이어, 플레이어컨트롤러 세개 만들어서

플레이어랑 플레이어콘트롤러는 미리 player 오브젝트에 붙여줌.

 

 

캐릭터매니저를 싱글톤으로 만들고, 거기에 플레이어 스크립트를 넣어줄거임.

플레이어 스크립트는 컨트롤러나 컨디션 같은 체력, 인터렉션(장비) 이런 기능들을 플레이어에 넣어줄거임

플레이어 컨트롤러에 직접 접근하는게 아니라 플레이어에 캐싱 한 다음 캐릭터매니저를 통해 접근할거임

>>?

 

CharacterManager 스크립트 작성

 

플레이어 스크립트 작성

public class Player : MonoBehaviour
{
    public PlayerController controller;

    private void Awake()
    {
        CharacterManager.Instance.Player = this;   //캐릭터매니저에 플레이어에 나 자신을 집어넣어준다
        controller = GetComponent<PlayerController>();  //겟컴포넌트로 플레이어컨트롤러를 찾아와서 집어넣어줌
    }
}

 

캐릭터매니저에서 작성해준 방어코드

 

플레이어 스크립트에서 Instance를 불러와주는데, 게임씬에 그게 없기 때문에

방어코드 ( 널일경우~!) 를 작성해놓았기 때문에 그래도 정상작동을 할 수 있다.

get
  {
      if(_instance == null)
      {
        _instance = new GameObject("CharacerManager").AddComponent<CharacterManager>();
      }
        return _instance;
  }

인스턴스에 새로운 게임오브젝트 만들고, 컴포넌트도 붙여준거임

그리고 그걸 _instance에 넣어준다음 리턴

 

이런 방어코드를 넣어줘야 하이어라키창에 깜빡하더라도 게임이 진행됨

시간 상 진행하는 모든것에 방어코드를 넣진 않겠지만,

진행하면서 방어코드를 넣으면 좋겠다 싶으면 넣어보는걸 추천

 

플레이어 컨트롤러 스크립트

 

적성 후 플레이어에 플레이어 인풋에 있는 이벤트에 Move를 넣어준다.

밑에는 스크립트가 아니라 하이어라키에 있는 Player 오브젝트 자체를 넣어줘야함!! 넣어주고나서 Player Controller의

OnMove 를 적용시켜줌

 

>> 그리고 원래  Update() 였는데 FixedUpdate() 로 바꿔준다.

큰 문제는 없지만 Riggidbody 등 물리연산을 사용할 때는 FixedUpdate로 사용해주는게 좋다

 

근데 작동이 안된다!

1. 플레이어컨트롤러 스크립트에서

public void OnMoveInput(InputAction.CallbackContext context)  //현재상태 받아오기
{
    if (context.phase == InputActionPhase.Performed) // Phase 분기점 - Started (키가 눌렸을때)는 한번만 작동해서 Performed로 바꿔줌
    {
        curMovementInput = context.ReadValue<Vector2>();
    }
    else if (context.phase == InputActionPhase.Canceled)
    {
        curMovementInput = Vector2.zero;
    }
}

여기가 원래 Started로 작성했는데

Started는 시작할때 한번 적용되는거라 계속 사용할 수 있게 Performed 로 바꿔준다

 

2. 플레이어컨트롤러 스크리트에서 무브 스피드가 0임

Move Speed가 0인데 이거를 한 5쯤으로 바꿔준다.

 

최댓값 최소값이랑 민감도도 넣어주고 카메라 컨테이너 넣어줌

 

그리고 Event 도 Move때랑 똑같이 넣어준다

근데 민감도 1 하니까 너무 정신없어서 0.1로 낮춰줌

 

근데 카메라가 날 기준으로 도는게 아니라

날 기준으로 원을 그리면서 돌고있음 시점이 내시점이 아님

>> 카메라가 좀 뒤에 있어서 그럼

 

메인카메라 값을 다 0으로 설정해주면 된다!

 

막간 코드설명

 void CameraLook()   //캐릭터를 돌리지 말고 일단 카메라만 돌려보자 
 {
     camCurXRot += mouseDelta.y * lookSensitivity;   //y값 * 민감도  (캐릭터가 좌우로 움직이려면 y축 기준으로 움직이기 때문에 X값에 y값을 넣어줘야함)
     camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook); // 최소값보다 작아지면 최소값 반환, 최댓값보다 많아지면 최댓값 반환
     cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0); // 로컬좌표로 돌려줌 (-cam~인 이유 실제로는 내렸을때 x값이 +가 되야해서 - 부호로 바꿔준고임)

     transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0); // 위아래 돌리는건 캐릭터 각도로 조정
 }

 

 

점프키 만들기

public void OnJumpInput(InputAction.CallbackContext context)
{
    if (context.phase == InputActionPhase.Started && IsGrounded())
    {
        _rigidbody.AddForce(Vector2.up * jumpPower, ForceMode.Impulse); // 순간적으로 힘을 확 줘서 점프
    }
}

온점프 만들어주고, 스크립트 인스펙터에서 JumpPower을 80정도로 넣어준 후 

이벤트에 Move, Look이랑 똑같이 OnJump 넣어준다!

 

is grounde 체크를 에브리띵으로 하고 플레이어만 빼주면 됨.

 

그리고 점프가 되지 않는 오류

 

- 플레이어랑 콜라이더랑 Y값 맞춰주는게 좋은듯함

안맞으면 점프가 안됀다고.ㅣ..

그리고 그라운드 체크 안해줘도 점프가 안된다.