유니티 플레이어 이동 - yuniti peulleieo idong

유니티 3D 개발일지 시작

유니티는 2D로만 몇번 다뤄본적이 있으나 3D쪽은 해본적이 없다. 일단 뭐든 만들어보면서 기능을 익혀 나가자. 장르는 일단 3D 쿼터뷰 액션 게임으로 만들어 볼 생각이다.

바닥 깔기

플레이어가 뛰어다닐 공간이 필요하니 바닥부터 깔자 큐브의 스케일값을 늘려서 바닥을 만들고 그리드 텍스쳐를 대충 그려서 Material 생성 적용했다.

플레이어 생성

플레이어 메시는 따로 없으니까 일단 캡슐과 큐브오브젝트로 만들었다. Player Object 에 Collider와 Rigidbody를 추가하고, Player 스크립트도 추가하였다.

플레이어 이동과 회전

스크립트 안에서 간단하게 방향키로 이동과 회전을 구현하였다. transform.position 포지션 값을 변경하는 방법도 있겠지만 충돌 처리를 위해서 Rigidbody에 힘을 가하는 방식으로 구현하였다. 이동하는 방향으로 회전하기 위해 `LookAt' 함수로 회전시켰다.

using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour { public float moveSpeed; private Rigidbody charRigidbody; void Start() { charRigidbody = GetComponent<Rigidbody>(); } void Update() { float hAxis = Input.GetAxisRaw("Horizontal"); float vAxis = Input.GetAxisRaw("Vertical"); Vector3 inputDir = new Vector3(hAxis, 0, vAxis).normalized; charRigidbody.velocity = inputDir * moveSpeed; transform.LookAt(transform.position + inputDir); } }

카메라 이동

카메라가 캐릭터를 따라다니게 해보자 Camera용 스크립트를 추가하였고, MainCamera Object에 Camera Script를 추가하였다. 그리고 Camera 스크립트에 따라다닐 targetTransform 변수에 Player Object를 지정하였다.

public class Camera : MonoBehaviour { public Transform targetTransform; public Vector3 CameraOffset; void Update() { transform.position = targetTransform.position + CameraOffset; } }

캐릭터를 카메라가 잘 따라다니는것을 확인 할 수 있다.

키보드에서 누른 값을 받아오자! Input

Update() { Input.method }

유니티의 Input 클래스는 사용자 입력을 감지하는 메서드를 모아둔 집합이다.
Input.method()가 실행 시점에서 누른 키 값을 반환한다.

그런데 Update() 메서드는 1초에 수십번씩 실행 되기 때문에
Update()메서드 안에서 입력을 받으면

짧은 간격으로 반복 실행하기에 플레이어는 입력이 즉각 반영 된다고 느낀다.

수평축 수직축의 입력값을 감지한다. 어떻게 ? GetAxis()

float Input.GetAxis(string axisName)

축에 대한 입력값을 숫자로 반환! 한다.
음의 방향 축에 대응 되는 버튼을 누르면 : -1.0
아무것도 누르지 않으면 : 0
양의 방향에 대응되는 버튼을 누르면 : +1.0

기본 설정으로 Horizontal축과 Vertical 축의 대응 입력키는
다음과 같다.

Horizontal : <- or A, 0 , -> or D
Vertical : W or ↑, 0 , S or ↓

void Update() float xinput = Input.GetAxis("Horizontal"); float zinput = Input.GetAxis("Vertinal"); float xSpeed = xInput * speed; float zSpeed = zInput * speed; Vector3 newVelocity = new Vector(xSpeed, 0f, zSpeed); playerRigidbody.velocity = newVelocity;
  • 속도를 나타내는 새로운 Vector3의 생성

x(좌우)축,z(전후)축을 조절할 것이므로
(GetAxis로 받는 값) * (속도) 를 새로운 새로운 벡터(newVelocity)에 할당

  • 리지드바디 컴포넌트의 속도변경

newVelocity를 플레이어 리지드바디의 속력에 할당한다.

컴포넌트 가져오기? GetCompnent()

원하는 타입의 컴포넌트를 자신의 게임 오브젝트에 찾아온다.
꺽쇠<> 안에는 가져올 타입의 컴포넌트를 할당한다.

void Start() { playerRigidbody = GetComponent<Rigidobody>(); }

의 뜻은 Player 게임 오브젝트에 리지드 바디 컴포넌트를 찾아서 player Rigidbody 변수에 할당한다는 의미이다.

변수처럼 생겼는데 메서드인 특수한 형태의 메서드, 프로퍼티(Property)

get * 이미 들어있는 값을 호출하면 자동적으로 get 호출 set * 값을 변경할 때, 자동적으로 호출된다. * set 호출시 변경될 값에 대해서 내장된 조건에 따라서 방어적으로 값을 할당할 수 있다.

실제적으로 해보자.

보통 입력을 감지하는 인풋 스크립트와 이동 스크립트를 2개로 나누어 짠다.

플레이어 인풋 스크립트에서 입력을 감지하고 다른 컴포넌트에 알려준다.

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() { // 게임오버 상태에서는 사용자 입력을 감지하지 않는다 if (GameManager.instance != null && GameManager.instance.isGameover) { move = 0; rotate = 0; fire = false; reload = false; return; } // move에 관한 입력 감지 move = Input.GetAxis(moveAxisName); // rotate에 관한 입력 감지 rotate = Input.GetAxis(rotateAxisName); // fire에 관한 입력 감지 fire = Input.GetButton(fireButtonName); // reload에 관한 입력 감지 reload = Input.GetButtonDown(reloadButtonName); } }

이제 이동 스크립트에서 변수를 가져와서 무브먼트 스크립트에 전달해서 만들어보자.

using UnityEngine; // 플레이어 캐릭터를 사용자 입력에 따라 움직이는 스크립트 public class PlayerMovement : MonoBehaviour { public float moveSpeed = 5f; // 앞뒤 움직임의 속도 public float rotateSpeed = 180f; // 좌우 회전 속도 private PlayerInput playerInput; // 플레이어 입력을 알려주는 컴포넌트 private Rigidbody playerRigidbody; // 플레이어 캐릭터의 리지드바디 private Animator playerAnimator; // 플레이어 캐릭터의 애니메이터 private void Start() { // 사용할 컴포넌트들의 참조를 가져오기 playerInput = GetComponent<PlayerInput>(); playerRigidbody = GetComponent<Rigidbody>(); playerAnimator = GetComponent<Animator>(); } // FixedUpdate는 물리 갱신 주기에 맞춰 실행됨 private void FixedUpdate() { // 물리 갱신 주기마다 움직임, 회전, 애니메이션 처리 실행 Rotate(); 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); } }

Toplist

최신 우편물

태그