시네머신을 사용하기 위해 패키지매니저에서 설치해야한다.

하이라키의 MainCamera를 선택하고 Cinemachine을 Add Component한다.

하이라키의 +를 누르고 Cinemachin>Virtual Camera를 선택한다.

이름을 FollowCam으로 바꾼다.

하이라키뷰에서 FollowCam을 선택하고 씬뷰에서 Y축을 이동시켜 인스펙터뷰에서 Y포지션을 5정도로 맞춘다.

하이라키뷰의 Player를 선택해 FollowCam의 CinemachineVirtualCamera의 Follow, LookAt에 연결해준다.

FollowCam은 Follow객체의 뒤에 따라다니고 시선은 LookAt을 본다. 비슷한것 같지만 위치와 로테이션의 타겟을 뜻한다.

사실 이 정도 효과는 Main Camera를 Player의 차일드로 하는 것으로 간단히 구현할 수 있지만. 시네머신은 Body, Aim등 다양한 컨트롤을 마련해놨지만 여기서는 설명하지 않겠습니다.

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

입력및 이동  (0) 2023.04.27
레벨아트및 플레이어 만들기  (0) 2023.04.27

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

 

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

3D 프로젝트를 하나  만들자.

3D오브젝트 플레인을 만들고 스케일을 5로한다.

프로젝트뷰에서 우클릭후 Material을 만들어 좋와하는 색깔을 만들고  끌어다 Plane에 적용한다.

플레이어 만들기

빈오브젝트를 만들고 이름을 Player로 변경한다.

3D오브젝트 Capsule을 하나 만들고 body로 이름바꾼다. Player의 차일드로 끌어놓고, Y Position을 1로 한다.

프로젝트뷰에서 우클릭후 Material을 만들어 좋와하는 색깔을 만들고  끌어다 Player에 적용한다.

리지드바디를 추가하고 Angular Drag를 20으로 하고 Constraints > Freeze Rotation x ,z 체크한다.

방향을 알기 쉽게 모자를 하나 만들어주자 Cube를 만들어 이름을 Cap으로 바꾸고 Player의 차일드로 끌어주고  사이즈를 스케일을 변경한다.

 

 

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

시네머신  (0) 2023.04.27
입력및 이동  (0) 2023.04.27

+ Recent posts