유니티 2D 총알 발사 방법에 대해 궁금해 하시는 분들이 많아서 단계별로 구현하는 과정을 보여 드리려고 합니다.
현재 씬 및 프로젝트 폴더, 에셋은 다음과 같이 되어 있습니다.
단순한 2D 스프라이트로 구성된 우주선과 미사일 게임 프리팹들이 있고, 이 중에서 우주선(space ship) 프리팹을 씬에 배치한 상태입니다. 각각의 프리팹에는 스프라이트 랜더러(Sprite Renderer)를 제외하고는 어떠한 스크립트나 컴포넌트가 붙어 있지 않습니다.
리지드 바디를 이용한 유니티 2D 총알 발사 방법
우선 미사일 프리팹에 Rigidbody 2D 컴포넌트를 붙여서 물리적인 힘으로 총알을 발사할 수 있는지 한번 보겠습니다. 가장 쉬운 유니티 2D 총알 발사 방법입니다.
다음과 같이 MissileLauncher 라는 이름의 C# 스크립트를 작성해서 씬에 있는 SpaceShip 게임 오브젝트에 붙이겠습니다.
코드의 내용은 다음과 같습니다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MissileLauncher : MonoBehaviour
{
// 미사일 프리팹
public GameObject missilePrefab;
// 미사일이 발사되는 순간의 속도
public float launchSpeed = 10.0f;
// Update is called once per frame
void Update()
{
// 플레이어가 Fire1 버튼을 눌렀는지를 체크
if (Input.GetButtonDown("Fire1"))
{
// 프리팹으로부터 새로운 미사일 게임 오브젝트 생성
GameObject missile = Instantiate(missilePrefab, transform.position, transform.rotation);
// 미사일로부터 리지드바디 2D 컴포넌트 가져옴
Rigidbody2D rb = missile.GetComponent<Rigidbody2D>();
// 미사일을 전방으로 발사
rb.AddForce(transform.up * launchSpeed, ForceMode2D.Impulse);
}
}
}
프로젝트 폴더에서 미사일 프리팹을 찾아서 인스펙터의 Missile Prefab 에 드래그 앤 드롭으로 연동합니다.
그런데 이 상태로 게임을 플레이해 보겠습니다. 코드에서 미사일 발사 버튼이 Fire1 으로 되어 있으므로 마우스 왼쪽 버튼을 클릭하면 미사일이 발사될 것입니다.
하지만 총알이 올라가다가 다시 아래로 떨어집니다.
이 경우, 가장 쉽게 해결할 수 있는 방법은 미사일의 Rigidbody 2D 의 Gravity Scale 의 값을 0 으로 바꿔 주는 것입니다.
이렇게 하면 발사된 미사일이 중력의 영향을 받지 않기 때문에 다시 뒤로 떨어지지 않게 됩니다.
물론 이렇게 하지 않고 다른 방식으로 미사일이 전진하게 하는 방법도 있습니다. 리지드 바디를 아예 사용하지 않고 미사일 프리팹의 인스턴스가 생성되는 순간 자동으로 전진하게 하는 코드를 작성해서 미사일에 붙이는 방법입니다.
리지드바디 없이 미사일 발사하기
위에서는 리지드바디를 이용해서 미사일을 발사했습니다. 하지만 물리 엔진 없이 단지 미사일의 위치 변화 계산만으로도 미사일 발사 및 이동을 처리할 수 있습니다.
이제 MissileLaucher.cs 에서 리지드바디 관련된 코드들을 삭제하겠습니다.
public class MissileLauncher : MonoBehaviour
{
public GameObject missilePrefab;
public float launchSpeed = 10.0f;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
GameObject missile = Instantiate(missilePrefab, transform.position, transform.rotation);
Rigidbody2D rb = missile.GetComponent<Rigidbody2D>();
rb.AddForce(transform.up * launchSpeed, ForceMode2D.Impulse);
}
}
}
이제 미사일 프리팹으로 가서 리지드 바디를 제거합니다.
이제 Missile.cs 라는 클래스를 새로 만들고 코드를 작성해 보겠습니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
}
미사일 이동 속도를 저장할 speed
변수를 추가하고 기본값을 10f로 설정합니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
public float speed = 10f; // 미사일 이동 속도
}
미사일의 수명을 저장할 lifetime
변수와 미사일 생성 시간을 저장할 spawnTime
변수를 추가합니다. lifetime
은 초기값으로 5초를 설정합니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
public float speed = 10f; // 미사일 이동 속도
private float lifetime = 5f; // 미사일 수명 (초)
private float spawnTime; // 미사일 생성 시간
}
Start()
메소드에서 미사일 생성 시간을 저장합니다. 이 값은 미사일이 생성되는 시점의 시간입니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
public float speed = 10f; // 미사일 이동 속도
private float lifetime = 5f; // 미사일 수명 (초)
private float spawnTime; // 미사일 생성 시간
void Start()
{
spawnTime = Time.time; // 현재 시간을 저장
}
}
Update()
메소드에서 미사일을 위쪽으로 이동시키고 일정 시간이 지난 미사일을 삭제하도록 합니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
...
void Start()
{
spawnTime = Time.time; // 현재 시간을 저장
}
void Update()
{
// 일정한 속도로 위쪽으로 이동
transform.position += new Vector3(0, speed * Time.deltaTime, 0);
}
}
마지막으로, `Update()` 메소드 안에서 미사일의 수명이 다 되었는지 확인하고, 수명이 다 된 경우 미사일을 삭제합니다.
using UnityEngine;
public class Missile : MonoBehaviour
{
public float speed = 10f; // 미사일 이동 속도
private float lifetime = 5f; // 미사일 수명 (초)
private float spawnTime; // 미사일 생성 시간
void Start()
{
spawnTime = Time.time; // 현재 시간을 저장
}
void Update()
{
// 일정한 속도로 위쪽으로 이동
transform.position += new Vector3(0, speed * Time.deltaTime, 0);
// 미사일의 수명이 다 되면 삭제
if (Time.time - spawnTime > lifetime)
{
Destroy(gameObject);
}
}
}
이제 미사일 스크립트가 완성되었습니다. 이 스크립트를 미사일 프리팹에 추가하면, 프리팹이 일정한 속도로 위쪽으로 이동하고 지정된 시간이 지난 뒤에 자동으로 삭제됩니다.
이제 게임을 실행하고 마우스 왼쪽 버튼(Fire1)을 클릭하면 리지드바디 없이도 미사일이 발사됩니다.
더 공부할 자료 - 개발 능력 다양화를 위한 학습의 필요성
유니티 엔진의 대안으로서, 인디 개발자들에게 선풍적인 인기를 끌고 있는 엔진이 바로 고도 엔진입니다. 혹시 고도 엔진을 배워 보려고 하신다면, 다음의 온라인 강의를 체크해 보시기 바랍니다.