본문 바로가기
게임 프로그래밍/게임개발 중급

게임개발 중급(23) - 3D 게임 만들기(3)

by jyppro 2023. 5. 13.

3D 게임 만들기(3)

저번 시간에는 Vertex Snapping(버택스 스내핑)을 이용해서 오브젝트를 특정 위치에 정확히 배치하여 무대를 만들었고, 3D 프로젝트를 시작하면 기본적으로 생성되는 메인카메라와 디렉셔널 라이트를 조정하여 게임 뷰에서 보일 화면에 대한 기본 설정을 하였습니다. 이번에는 2D 플랫포머 게임 만들기에서 했던 것처럼, 아이템을 생성하고 플레이어 컨트롤을 통해 움직이며, 점수를 획득하는 것을 하겠습니다.

 

아이템 생성

아이템을 생성할 때에는 프리팹을 사용하는 것이 유용합니다. 하지만 프리팹을 사용해야 할 이유가 없다면 꼭 사용하지 않아도 됩니다. 프리팹을 사용하기 좋은 예시로는, 사용하는 오브젝트가 반복적으로 생성되거나, 해당 오브젝트의 많은 컴포넌트가 들어가 있을 때 등이 있습니다. 저는 예제로서 10개의 아이템이 생성된 상태로 게임을 시작할 것이기 때문에 프리팹을 사용하지 않고 3D 오브젝트의 Sphere를 생성하여 사용하겠습니다.

 

아이템-생성
아이템 생성

item이라 이름을 붙히고 복사하여 각자 다른 위치에 10개를 생성하여 배치했습니다. 저희는 이것을 플레이어가 먹어서 점수를 올리는 코인과 동일하게 사용할 것이기 때문에, Sphere Collider를 적용시켜 줍니다. 복사하기 전 원본에 컴포넌트를 적용시킨 뒤 복사하면 함께 복사가 됩니다.

 

마찬가지로, 플레이어도 PlayerContorller 스크립트를 작성하여 충돌처리와 움직임을 만들어 줄 것이기 때문에 Rigidbody와 Capsule Collider를 적용시켜 줍니다. 이제 PlayerController 스크립트를 작성해 보겠습니다.

 

PlayerController

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    Rigidbody rigid;
    GameObject item;

    float jumpForce = 5.0f;
    float walkForce = 5.0f;
    int key = 0;

    void Start()
    {
        this.rigid = GetComponent<Rigidbody>();
    }

    void Update()
    {
        //점프
        if(Input.GetKeyDown(KeyCode.Space) && this.rigid.velocity.y == 0f){
            rigid.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }

        //방향키로 움직이기
        if(Input.GetKey(KeyCode.RightArrow)){ // 오른쪽
            key = 1;
            this.rigid.AddForce(transform.right * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.LeftArrow)){ // 왼쪽
            key = -1;
            this.rigid.AddForce(transform.right * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.UpArrow)){ // 앞
            key = 1;
            this.rigid.AddForce(transform.forward * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.DownArrow)){ // 뒤
            key = -1;
            this.rigid.AddForce(transform.forward * key * this.walkForce);
        }
    }

    //아이템 먹기
    void OnTriggerEnter(Collider other)
    {
        Destroy(other.gameObject);
    }
}

우선 가장 기본적인 형태의 움직임인 방향키를 사용한 움직임, 그리고 점프에 대한 스크립트를 작성하였습니다. 아이템과의 충돌처리도 일단 해주었습니다. 여기서는 기존의 2D 게임과 다른점이 보입니다. 바로 Vector3의 값을 사용한다는 것입니다. 점프에 대한 코드를 작성할 때, rigidbody velocity의 y값이 0일 때를 and 조건으로 묶어주었는데, 이것은 이전에 isGround와 같은 바닥처리를 해주는 방식입니다. 다단점프가 되지 않도록 막아주는 코드입니다.

 

이렇게 작성한 뒤 실행하면, 플레이어는 방향키와 스페이스바를 통해 상하좌우로 움직이고 점프를 하며, 아이템을 먹을 수 있게 됩니다.

움직여서-아이템먹기
움직임을 통해 아이템을 먹은 모습

 

점수 UI 생성 및 적용

이제 플레이어가 아이템을 먹었을 때, UI를 통해 점수가 올라가는 것을 표시해 주도록 하겠습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
using UnityEngine;

public class Sample : MonoBehaviour
{
    Rigidbody rigid;
    GameObject item;
    float jumpForce = 5.0f;
    float walkForce = 5.0f;
    int key = 0;
    int score = 0;

    void Start()
    {
        this.rigid = GetComponent<Rigidbody>();
        this.item = GameObject.Find("Score");
    }

    void Update()
    {
        //점프
        if(Input.GetKeyDown(KeyCode.Space) && this.rigid.velocity.y == 0f){
            rigid.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
        }

        //방향키로 움직이기
        if(Input.GetKey(KeyCode.RightArrow)){ // 오른쪽
            key = 1;
            this.rigid.AddForce(transform.right * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.LeftArrow)){ // 왼쪽
            key = -1;
            this.rigid.AddForce(transform.right * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.UpArrow)){ // 앞
            key = 1;
            this.rigid.AddForce(transform.forward * key * this.walkForce);
        }
        if(Input.GetKey(KeyCode.DownArrow)){ // 뒤
            key = -1;
            this.rigid.AddForce(transform.forward * key * this.walkForce);
        }
    }

    //아이템 먹으면 점수 올라가는 기능
    void OnTriggerEnter(Collider other)
    {
        score += 10;

        if(score >= 0){
            this.item.GetComponent<Text>().text = "Score: " + score.ToString();
        }
        
        Destroy(other.gameObject);
    }
}

이전의 PlayerController 코드에 score 변수를 추가한 뒤, UI로 생성한 Score를 초기화 시켜줍니다. 그리고 아이템과 부딪혔을 때, 변수 score에 10씩 더해주고, score가 0보다 크거나 같으면 UI의 Text를 score값으로 만들어 줍니다.

 

이렇게 작성한 뒤에 실행해보면, 아이템을 먹을 때마다 스코어가 올라가는 것이 UI에 적용되는 것을 볼 수 있습니다.

점수UI-사용
점수가 잘 적용되는 모습

 

<NEXT>

이번시간에는 아이템을 만들고, 방향키를 사용한 플레이어의 움직임 및 아이템 획득처리, 점수UI 처리를 동시에 진행하였습니다. 이전에 이미 다뤘던 내용과 비슷하기 때문에 빠르게 넘어갔습니다만, 만약 더 자세한 설명이 필요하다면 "2D 플랫포머 게임 만들기" 에서 다뤘던 글을 한번 보시는 것을 추천드립니다. 다음에는 UI를 사용한 플레이어의 움직임 및 다양한 방식의 움직임에 대해 알아보겠습니다. 감사합니다.