Unity 강의 정리 4-2장: 소코반 게임 만들기 - 플레이어 조작 🎮

나무에물주기·2023년 8월 14일
1

Unity

목록 보기
5/21
post-thumbnail

인프런에 있는 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리하는 글입니다!

이번 장에서는 소코반 게임의 플레이어 조작 기능을 구현할 것이다. 플레이어의 이동과 관련된 코드와 컴포넌트를 다룰 예정이다.

1. start 함수, update 함수 🔄

Unity에서는 두 가지 주요 함수를 사용하여 게임의 로직을 제어한다.

  • Start(): 이 함수는 게임 오브젝트가 처음 활성화될 때 한 번만 호출된다. 변수의 초기화나 게임 시작 시 한 번만 수행해야 할 로직을 넣는다. 예를 들어, 플레이어의 초기 위치나 점수를 설정하는 등의 작업이 이 함수 안에 들어간다.
void Start()
{
    // 초기 위치 설정
    transform.position = new Vector3(0, 0, 0);
}
  • Update(): 이 함수는 매 프레임마다 호출되며, 게임의 주 로직이 들어간다. 플레이어의 이동, 적의 생성, 시간 관리 등 게임 상태를 지속적으로 업데이트하는 데 사용된다.
void Update()
{
    // 플레이어의 이동 로직
}

2. update 함수 안에서 유저 입력(키보드) 처리하기 ⌨️

Unity에서 플레이어의 키보드 입력은 주로 Update() 함수 내에서 처리된다. 다음은 플레이어의 이동을 WASD 키로 조작하는 기본적인 방법을 보여준다.

  • Input.GetKey: 특정 키가 눌러져 있는 동안 true를 반환한다. 이를 통해 눌린 키에 따라 플레이어에 힘을 가하거나 방향을 바꾼다.
void Update()
{
    if(Input.GetKey(KeyCode.W)) 
      playerRigidbody.AddForce(0, 0, speed);  // W 키를 누르면 z축 방향으로 이동

    if(Input.GetKey(KeyCode.A)) 
      playerRigidbody.AddForce(-speed, 0, 0); // A 키를 누르면 x축 방향으로 음수 방향으로 이동

    if(Input.GetKey(KeyCode.S)) 
      playerRigidbody.AddForce(0, 0, -speed); // S 키를 누르면 z축 방향으로 음수 방향으로 이동

    if(Input.GetKey(KeyCode.D)) 
      playerRigidbody.AddForce(speed, 0, 0);  // D 키를 누르면 x축 방향으로 이동
}

이렇게 Update() 함수 내에서 Input.GetKey를 사용하면 각 키 입력에 따른 플레이어의 이동을 제어할 수 있다. 키를 누르고 있는 동안 해당 방향으로의 힘이 지속적으로 가해진다.


3. Input (GetKey, KeyCode), Input.GetKey의 단점 🚧

Unity에서 키보드 입력을 처리하는 방법 중 하나는 Input.GetKey 함수를 사용하는 것이다. 이 함수는 특정 키가 눌러져 있는 동안 true를 반환한다.

if(Input.GetKey(KeyCode.W))
{
    // W 키가 눌러져 있는 동안 실행되는 코드
}

하지만 Input.GetKey의 사용에는 몇 가지 단점이 있다:

  1. 이진 입력: 키가 눌러져 있는지 아닌지만 확인할 수 있다. 키를 얼마나 강하게 눌렀는지와 같은 연속적인 입력 값은 얻을 수 없다.
  2. 방향 제한: 대각선 방향 이동과 같은 복잡한 입력 처리가 어려울 수 있다.
  3. 플랫폼 종속성: 다른 장치나 플랫폼에서의 입력 처리가 복잡해질 수 있다.

이러한 단점으로 인해 복잡한 입력 로직을 처리하거나 다양한 플랫폼을 지원해야 할 때는 다른 입력 처리 방법을 고려해야 할 수도 있다.


4. Input.Axix 🕹️

Input.GetAxis는 Unity에서 연속적인 입력 값을 처리하는 데 사용되는 함수다. 이 함수는 설정된 축의 값을 -1에서 1 사이의 부동 소수점 값으로 반환한다.

float inputX = Input.GetAxis("Horizontal");
float inputZ = Input.GetAxis("Vertical");

Input.GetAxis의 장점:

  1. 연속적인 값: 키를 얼마나 강하게 눌렀는지와 같은 연속적인 입력 값을 얻을 수 있다.
  2. 방향 지원: 대각선 방향 이동과 같은 복잡한 입력도 처리할 수 있다.
  3. 플랫폼 독립성: 다양한 장치와 플랫폼에서의 입력 처리가 간편하다.
  4. 스무딩: 입력 값에 스무딩을 적용하여 더 부드러운 조작감을 제공할 수 있다.
void Update()
{
    float inputX = Input.GetAxis("Horizontal");
    float inputZ = Input.GetAxis("Vertical");
    playerRigidbody.AddForce(inputX * speed, 0, inputZ * speed);
}

Input.GetAxis를 사용하면 키보드 뿐만 아니라 조이스틱과 같은 입력 장치도 쉽게 처리할 수 있다. 이로 인해 플레이어의 조작이 더 자연스럽고 복잡한 입력 로직도 구현할 수 있다.


5. 관성 없애기, 문제점, 해결 방법 🛑

Unity에서 플레이어의 움직임에 관성을 없애고 싶을 때, Rigidbody의 velocity 변수 값을 직접 변경할 수 있다.

Vector3 velocity = new Vector3(inputX, 0, inputZ);
velocity = velocity * speed;
playerRigidbody.velocity = velocity;

문제점: 이 방법은 떨어지는 속도가 이상해지는 등의 문제를 초래할 수 있다. 플레이어가 바닥을 벗어나면, 중력을 받지 않거나 아주 천천히 떨어지는 이상한 모습이 나타날 수 있다.

해결 방법: 원래 y축의 속도를 보존하여 문제를 해결할 수 있다.

float fallSpeed = playerRigidbody.velocity.y;  // 원래 y의 속도를 보존
Vector3 velocity = new Vector3(inputX, 0, inputZ);
velocity = velocity * speed;
velocity.y = fallSpeed;  // 원래 y로 설정
playerRigidbody.velocity = velocity;  // 최종 속도 설정

이렇게 하면 관성을 없애면서도 중력에 대한 영향을 그대로 받게 해 문제를 해결할 수 있다.


6. GetComponent() 🧩

Unity에서 특정 컴포넌트를 가져오려면 GetComponent() 함수를 사용한다. 이 함수는 해당 컴포넌트가 붙어 있다면 찾아서 반환해준다.

Rigidbody playerRigidbody;
void Start()
{
    playerRigidbody = GetComponent<Rigidbody>(); // Rigidbody 컴포넌트 찾아서 반환
}

이 함수를 사용하면 스크립트에서 직접 컴포넌트를 참조할 수 있다.


🎓 정리

이번 장에서는 플레이어의 조작과 관련된 여러 기능과 컴포넌트를 배웠다. 다양한 입력 방식과 물리적 효과를 활용하여 플레이어의 움직임을 구현하였다.

전체 코드
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player : MonoBehaviour
{
    // 플레이어의 이동 속도
    public float speed = 10f;

    // 플레이어의 리지드바디 컴포넌트
    Rigidbody playerRigidbody;

    // 게임이 시작될 때 한 번만 호출되는 함수 -> 초기화
    void Start()
    {
        // GetComponent<타입>() : 타입에 해당하는 컴포넌트를 찾아서 반환
        playerRigidbody = GetComponent<Rigidbody>();
    }

    // 매 프레임마다 호출되는 함수 -> 유저 입력을 받아서 처리
    void Update()
    {
        // GetAxis() : 키보드 입력을 받아서 -1 ~ 1 사이의 값을 반환
        float inpuitX = Input.GetAxis("Horizontal"); // 조이스틱 대응 가능
        float inputZ = Input.GetAxis("Vertical"); 
        float fallSpeed = playerRigidbody.velocity.y; // 중력에 의해 떨어지는 속도를 유지시키기 위해

        // 방향 * 속도 = 속도 벡터
        Vector3 velocity = new Vector3(inpuitX, 0f, inputZ);

        velocity = velocity * speed; // 방향 * 속도
        velocity.y = fallSpeed; // 중력에 의해 떨어지는 속도를 유지시키기 위해

        // 리지드바디의 속도를 velocity로 변경
        playerRigidbody.velocity = velocity;
    }
}
profile
개인 공부를 정리함니다

0개의 댓글