이번게임에서는 키보드의 입력과 플레이어의 이동 로직을 분리한다. 이렇게 하는것이 업그레이드 관리에 용이하기 때문이다. 우선 입력부분부터 만들어본다.

 

Player를 선택하고 Add Component>Script add하고 이름을 PlayerInput으로 바꾼다.

Input.GetAxis()에 사용될 스트링의 선언이다.

public string moveAxisName = "Vertical"; // 앞뒤 움직임을 위한 입력축 이름
public string rotateAxisName = "Horizontal"; // 좌우 회전을 위한 입력축 이름
public string fireButtonName = "Fire1"; // 발사를 위한 입력 버튼 이름
public string reloadButtonName = "Reload"; // 재장전을 위한 입력 버튼 이름

키보드 입력을 받아올 변수의 정의 인데 잘보면 프로퍼티라고 클래스이다. 변수와 다른점을 클래스 안에서 필요에 따라 좀더 유연한 정의가 가능하다는 점이다. 

public float move { get; private set; } // 감지된 움직임 입력값
public float rotate { get; private set; } // 감지된 회전 입력값
public bool fire { get; private set; } // 감지된 발사 입력값
public bool reload { get; private set; } // 감지된 재장전 입력값

Update()함수는 Input.GetAxis()함수를 이용해 입력값을 읽어와 프로퍼티에 저장한다.

PlayerInput 전체코드

using UnityEngine;

// 플레이어 캐릭터를 조작하기 위한 사용자 입력을 감지
// 감지된 입력값을 다른 컴포넌트들이 사용할 수 있도록 제공
public class PlayerInput : MonoBehaviour {
    public string moveAxisName = "Vertical"; // 앞뒤 움직임을 위한 입력축 이름
    public string rotateAxisName = "Horizontal"; // 좌우 회전을 위한 입력축 이름
    public string fireButtonName = "Fire1"; // 발사를 위한 입력 버튼 이름
    public string reloadButtonName = "Reload"; // 재장전을 위한 입력 버튼 이름

    // 값 할당은 내부에서만 가능
    public float move { get; private set; } // 감지된 움직임 입력값
    public float rotate { get; private set; } // 감지된 회전 입력값
    public bool fire { get; private set; } // 감지된 발사 입력값
    public bool reload { get; private set; } // 감지된 재장전 입력값

    // 매프레임 사용자 입력을 감지
    private void Update() {
        // move에 관한 입력 감지
        move = Input.GetAxis(moveAxisName);
        // rotate에 관한 입력 감지
        rotate = Input.GetAxis(rotateAxisName);
        // fire에 관한 입력 감지
        fire = Input.GetButton(fireButtonName);
        // reload에 관한 입력 감지
        reload = Input.GetButtonDown(reloadButtonName);
    }
}

 

이제 움직임을 담당할 PlayerMovement를 만들어본다.

앞뒤 움직임 속도, 회전속도를 지정할 변수를 설정한다.

public float moveSpeed = 5f; // 앞뒤 움직임의 속도
public float rotateSpeed = 180f; // 좌우 회전 속도

Start()함수에서  PlayerInput(), Rigidbody()컴포넌트 참조를 가져온다. PlayerInput()도 Player오브젝트의 컴포넌트로 추가되어 있어야한다.

private void Start() {
    // 사용할 컴포넌트들의 참조를 가져오기
    playerInput = GetComponent<PlayerInput>();
    playerRigidbody = GetComponent<Rigidbody>();
}

FixedUpdate()함수는 Unity에서 Rigidbody컴포넌트 처리(물리갱신주기)가 이루어지는 곳이다. 여기서 움직임을 처리한다. Update()는 화면갱신주기이다.

private void FixedUpdate() {
    // 회전 실행
    Rotate();
    // 움직임 실행
    Move();

    // 입력값에 따라 애니메이터의 Move 파라미터 값을 변경
    //playerAnimator.SetFloat("Move", playerInput.move);
}

Move()와  Rotate()는 Rigidbody.MovePosition()메써드나 position을 변경해도 된다. 주의할점은 게임오브젝트의 transform.position을 사용해도 되지만 Rigidbody컴포넌트가 추가되어 있을때는 계산의 엉킴을 방지하기위해 리지드바디에서 처리하는게 좋은듯 하다.

private void Move() {
    // 상대적으로 이동할 거리 계산
    Vector3 moveDistance =
        playerInput.move * transform.forward * moveSpeed * Time.deltaTime;
    // 리지드바디를 통해 게임 오브젝트 위치 변경
    playerRigidbody.MovePosition(playerRigidbody.position + moveDistance);
    //playerRigidbody.position += moveDistance;
}

Quaternion.rotation의 회전의 + 가 아니라 * 이다. 행렬계산을 해야하기 때문이다. 따라서 회전시키고 싶은 오일러각(Vector3)를 Quaternion.Euler()로 변경시켜 곱해줘서 회전을 하게 만들어 준다.

private void Rotate() {
    // 상대적으로 회전할 수치 계산
    float turn =
        playerInput.rotate * rotateSpeed * Time.deltaTime;
    // 리지드바디를 통해 게임 오브젝트 회전 변경
    playerRigidbody.rotation = playerRigidbody.rotation * Quaternion.Euler(0, turn, 0f);
}

PlayerMovement 전체코드, 이번 강좌에서는 Animator를 사용하지 않기 때문에 주석처리되어있다

using UnityEngine;

// 플레이어 캐릭터를 사용자 입력에 따라 움직이는 스크립트
public class PlayerMovement : MonoBehaviour {
    public float moveSpeed = 5f; // 앞뒤 움직임의 속도
    public float rotateSpeed = 180f; // 좌우 회전 속도

    //private Animator playerAnimator; // 플레이어 캐릭터의 애니메이터
    private PlayerInput playerInput; // 플레이어 입력을 알려주는 컴포넌트
    private Rigidbody playerRigidbody; // 플레이어 캐릭터의 리지드바디

    private void Start() {
        // 사용할 컴포넌트들의 참조를 가져오기
        playerInput = GetComponent<PlayerInput>();
        playerRigidbody = GetComponent<Rigidbody>();
        //playerAnimator = GetComponent<Animator>();
    }

    // FixedUpdate는 물리 갱신 주기에 맞춰 실행됨
    private void FixedUpdate() {
        // 회전 실행
        Rotate();
        // 움직임 실행
        Move();

        // 입력값에 따라 애니메이터의 Move 파라미터 값을 변경
        //playerAnimator.SetFloat("Move", playerInput.move);
    }

    // 입력값에 따라 캐릭터를 앞뒤로 움직임
    private void Move() {
        // 상대적으로 이동할 거리 계산
        Vector3 moveDistance =
            playerInput.move * transform.forward * moveSpeed * Time.deltaTime;
        // 리지드바디를 통해 게임 오브젝트 위치 변경
        playerRigidbody.MovePosition(playerRigidbody.position + moveDistance);
    }

    // 입력값에 따라 캐릭터를 좌우로 회전
    private void Rotate() {
        // 상대적으로 회전할 수치 계산
        float turn =
            playerInput.rotate * rotateSpeed * Time.deltaTime;
        // 리지드바디를 통해 게임 오브젝트 회전 변경
        playerRigidbody.rotation = playerRigidbody.rotation * Quaternion.Euler(0, turn, 0f);
    }
}

 

 

'유니티좀비게임 > 레벨아트와 플레이어' 카테고리의 다른 글

시네머신  (0) 2023.04.27
레벨아트및 플레이어 만들기  (0) 2023.04.27

+ Recent posts