본문 바로가기

Unity/▶ Game Development: Dodge

[Dodge] #4. 탄알 생성

728x90
반응형

탄알 게임 오브젝트를 생성하고 필요한 컴포넌트를 추가해보자.

탄알은 생성된 후 앞쪽 방향으로 일정 속도로 나아가며, 충돌한 오브젝트가 플레이어면 해당 게임 오브젝트를 파괴한다.

 

탄알 게임 오브젝트 생성

탄알이 될 Bullet 게임 오브젝트를 생성한다. 구를 생성하고 크기를 줄여 탄알로 사용한다.

탄알 오브젝트를 생성한다.

  1. 하이어 라키 > Create > 3d Object > Sphere
  2. 크기(scale)를 위의 사진과 같이 (0.5,0.5,0.5)로 설정한다.
  3. 위치를 (0,5,0)로 설정한다.
  4. 프로젝트 창에서 새로운 Material을 생성하고 Bullet에 드래그&드롭하여 색을 설정한다.

리지드 바디 컴포넌트 설정

탄알이 속도를 가지도록 Bullet 게임 오브젝트에 리지드 바디 컴포넌트를 추가한다.

이때 리지드 바디가 적용된 오브젝트는 물리적인 상호작용이 가능하고 중력의 영향으로 밑으로 떨어지게 된다. 이를 막기 위해 리지드 바디 컴포넌트의 중력 사용 필드체크 해제한다.

중력 필드 체크 해제

Use Gravity의 체크 박스를 해제한다.

 

콜라이더 설정하기

Bullet 게임 오브젝트에는 구 콜라이더가 추가되어있어 물리적인 표면이 존재한다.

따라서 Bullet 게임 오브젝트는 콜라이더를 가진 다른 게임 오브젝트와 충동하면 튕겨나간다.

 

트리거 콜라이더

트리거 콜라이더는 충동한 물체를 밀어내는 물리적인 표면이 없다. 그래서 트리거 콜라이더는 다른 일반 콜라이더와 겹치거나 뚫고 지나갈 수 있지만 충돌 자체는 감지한다.

따라서 트리거 콜라이더는 충돌이 감지되었을 때 어떤 기능을 사용하는 방아쇠 역할로 사용된다.

예를 들어 플레이어가 특정 영역을 진입했는지 확인할 때  사용된다.

 

왼쪽부터 박스콜라이더, 캡슐콜라이더, 스피어콜라이더(출처:https://ariel1910.tistory.com/entry/%EC%9C%A0%EB%8B%88%ED%8B%B0-4-%EC%BD%9C%EB%9D%BC%EC%9D%B4%EB%8D%94collider-%ED%8A%B8%EB%A6%AC%EA%B1%B0)
인스펙터 창에서 콜라이더를 설정할 수 있다.

Is Trigger 체크 박스를 체크하여 트리거 콜라이더로 사용할 수 있다.

 

Bullet 프리팹 설정

탄알 생성기를 이용하여 게임 오브젝트를 게임 도중 실시간으로 복제 생성해보도록 하자.

 

탄알 생성기 입장에서는 생성할 Bullet 게임 오브젝트의 원본 게임 오브젝트가 필요하다. 따라서 Bullet 게임 오브젝트를 프리 팹으로 만들어 이를 해결하자.

 

프리팹

  • 프리 팹은 언제든지 재사용할 수 있는 미리 만들어진 게임 오브젝트 에셋 파일이다. 
  • 비슷한 오브젝트를 여러 개 만드는 번거로움을 줄이기 위해 프리 팹을 사용한다.

게임 오브젝트를 프리팹으로 만들면 나중에 해당 게임 오브젝트와 똑같은 게임 오브젝트를 프리팹에서 복제 생성할 수 있다. 

프리팹은 파일로 저장되므로 현재 씬 뿐만 아니라 다른 씬에서도 사용할 수 있다.

 

프리팹

Bullet 프리팹 만들기

1. Bullet 게임 오브젝트를 하이어 라키 창에서 프로젝트 창으로 드래그&드롭

- 프로젝트 창에 Bullet 프리팹이 생성된 것을 확인할 수 있다. 하이어 라키 창에 있는 Bullet 게임 오브젝트는 이름이 파란색으로 표시된다.

 

2. 프로젝트 창의 Bullet 프리팹을 하이어 라키 창으로 드래그&드롭

- (1)에서 설정한 프리 팹으로 같은 구성의 오브젝트를 복제 생성이 가능하다.

프로젝트 창에 프리팹이 생성된 것을 확인할 수 있다.

 

탄알 스크립트 생성

Bullet 스크립트 생성

  1. 프로젝트 > Create > C# Script
  2. 생성된 C# 스크립트를 Bullet으로 변경
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet : MonoBehaviour
{
    // Start is called before the first frame update
    public float speed = 8f;
    private Rigidbody bulletRigidbody;
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Bullet 스크립트에 필요한 변수인 speed와 bulletRigidbody를 선언한다.

speed의 접근 한정자가 public이기 때문에 speed에 할당된 값을 변경할 수 있다.

 

탄알 속도 지정하기

Bullet 스크립트가 실행될 때 Start() 메서드에서 Bullet 게임 오브젝트의 리지드 바디 컴포넌트를 bulletRigidbody에 할당해야 한다.

그리고는 bulletRigidbody.velocity로 탄알의 속도를 변경한다.

public float speed = 8f;
private Rigidbody bulletRigidbody;
void Start()
{   
    bulletRigidbody = GetComponent<Rigidbody>();
    bulletRigidbody.velocity = transform.forward * speed;
}
bulletRigidbody에 GetComponent 메서드를 이용하여 리지드 바디를 할당하고,
GetComponent.velocity의 값에 Transform.forward * speed를 대입한다.

 

이때 Transform.forward * speed는 앞쪽 방향에 이동 속력을 곱해 '게임 오브젝트의 앞쪽 방향으로 speed 만큼의 속도'를 표현한 값이다. Transform.forward은 Vector3 타입의 변수이다.

 

따라서 총알은 앞으로 초당 speed 만큼 이동한다.

transform

Transform 타입의 transform은 자신의 게임 오브젝트의 트랜스폼 컴포넌트로 바로 접근하는 변수이다.

 

트랜스폼

트랜스폼 컴포넌트는 게임 오브젝트의 위치, 크기, 회전을 담당하는 컴포넌트이다.

따라서 모든 게임 오브젝트가 하나씩 가지고 있으며 가장 자주 사용된다.

 

편의상 유니티의 C# 스크립트들은 자신의 게임 오브젝트의 트랜스폼 컴포넌트를 코드 상에서 transform 변수로 즉시 접근할 수 있도록 구성돼있다. 따라서 트랜스폼 컴포넌트는 GetComponent을 거칠 필요가 없다.

 

transform.forward에 바로 접근하여 forward 변수로 게임 오브젝트의 앞쪽 방향을 알 수 있다.
 
 

탄알 자동 파괴

사라지지 않고 화면 밖으로 날아간 탄알이 사라지지 않으면 불필요한 메모리 낭비를 초래하므로 생성된 후 일정 시간이 지난 탄알은 자동으로 파괴되는 알고리즘을 만들어보자.

void Start()
    {   
        bulletRigidbody = GetComponent<Rigidbody>();
        bulletRigidbody.velocity = transform.forward * speed;

        //3초 후 게임 오브젝트 파괴
        Destroy(gameObject,3f);
    }

Destroy() 메서드

Destroy 메서드는 자신의 게임 오브젝트를 파괴한다.

Destroy(Object ojt,float time)

Destroy 메서드는 두 번째 인자 값으로 파괴되는 딜레이를 줄 수 있으며 두 번째 인자가 없으면 즉시 파괴된다.

 

탄알의 충돌 처리

충돌 이벤트 메서드

유니티에서 콜라이더를 가진 두 물체는 충돌 시 자신이 충돌했다는 사실을 알 수 없는데, 그 대신 충돌했음을 알려주는 메시지가 각각의 물체에 보내지게 된다. 이 충돌 메시지를 통해 두 컴포넌트는 충돌 사실을 파악하고 충돌에 대응하는 메서드를 실행한다.

 

충돌 메시지에는 충돌한 상대방 게임 오브젝트에 대한 정보도 첨부된다. 이는 각각의 충돌 상대에 대한 오브젝트의 정보이다.

여기서 중요한 점은 충돌 메시지를 발생시키는 것은 리지드 바디 컴포넌트로, 메시지를 보내기 위해선 리지드 바디 컴포넌트를 가지고 있어야한다!

 

게임 오브젝트와 컴포넌트를 충돌 종류에 따라 OnTriggerEnter 혹은 OnCollisionEnter 메시지를 받는다.

 

[이벤트 발생]

OnCollisionEnter 계열: 일반 충돌 OnCollisionEnter(Collision collision) 충돌한 순간
OnCollisionStay(Collision collision) 충돌하는 동안
OnCollisionExit(Collision collision) 충돌했다가 분리되는 순간
OnTriggerEnter 계열: 트리거 충돌 OnTriggerEnter(Collider other) 충돌한 순간
OnTriggerStay(Collider other) 충돌하는 동안
OnTriggerExit(Collider other) 충돌했다가 분리되는 순간

[통과 여부]

OnCollisionEnter 계열: 일반 충돌 충돌한 두 콜라이더는 서로 통과하지 않고 밀어냄
OnTriggerEnter 계열: 트리거 충돌 충돌한 두 콜라이더는 서로 통과하여 지나감

OnTrigger 게열의 메서드가 실행 될때에는 Collider값으로 들어오는데, 충돌한 상대방 게임 오브젝트의 정보가 필요없기 때문이다.

 

이때, 충돌한 두 콜라이더 중 하나 이상이 트리거 콜라이더일때 양쪽에서 트리거 충돌 메서드가 발생한다.

 

탄알의 충돌 감지 구현

Bullet 게임 오브젝트의 콜라이더 컴포넌트는 트리거 콜라이더이므로 OnTriggerEnter()을 사용한다.

void OntriggerEnter(Collider other){
    if(other.tag == "Player"){
        PlayerController playerController = other.GetComponent<PlayerController>();
        if(playerController != null) playerController.Die();
    }
}

tag 메서드

if(other.tag == "Player")

other을 통해 충돌한 상대방 게임 오브젝트의 태그가 Player인지 확인한다.

게임 오브젝트나 컴포넌트를 tag라는 변수를 제공하여 자신의 게임 오브젝트의 태그가 무엇인지 알려준다.

PlayerController playerController = other.GetComponent<PlayerController>();
if(playerController != null) playerController.Die();

충돌한 게임 오브젝트가 Player 게임 오브젝트가 맞다면 상대방 게임 오브젝트로부터 PlayerController 컴포넌트를 가져온다. 이때 컴포넌트를 가져오기 위해 GetComponent 메서드를 사용한다.

 

other.GetComponent<PlayerController>(); 가 실행되면 other의 게임 오브젝트에 추가된 PlayerController 타입의 컴포넌트를 playerController라는 변수에 할당한다.

전체 코드

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

public class Bullet : MonoBehaviour
{
    // Start is called before the first frame update
    public float speed = 8f;
    private Rigidbody bulletRigidbody;
    void Start()
    {   
        bulletRigidbody = GetComponent<Rigidbody>();
        bulletRigidbody.velocity = transform.forward * speed;

        //3초 후 게임 오브젝트 파괴
        Destroy(gameObject,3f);
    }

    // Update is called once per frame
    void OntriggerEnter(Collider other){

        if(other.tag == "Player"){
            PlayerController playerController = other.GetComponent<PlayerController>();
            if(playerController != null) playerController.Die();
        }
    }
}

Bullet 게임 오브젝트 완성

프리팹과 연도된 게임 오브젝트에서 Apply All 버튼을 누르면 해당 게임 오브젝트의 변경 사항이 프리팹에 반영된다.

728x90
반응형

'Unity > ▶ Game Development: Dodge' 카테고리의 다른 글

[Dodge] #6. 바닥 회전  (0) 2022.03.02
[Dodge] #5. 탄알 생성기  (0) 2022.02.26
[Dodge] #3. 스크립트 개선하기  (0) 2022.02.24
[Dodge] #2. 플레이어  (0) 2022.02.04
[Dodge] #1. 게임 베이스 생성  (0) 2022.02.04
댓글