-
[Unity]유니티 입문하기 6-3(투사체 발사)프로그래밍 2023. 8. 2. 19:02
이전 글에서는 Input.GetKey() 메서드를 활용해 키 입력이 있었을 때 오브젝트를 이동시키는 법에 대해 배워봤습니다.
이번에는 프리팹(Prefab)과 리지드바디(Rigidbody)를 이용해 투사체를 만들어보도록 하겠습니다.
투사체를 발사하는 기능을 만들 때, 구현해야 하는 것은 다음과 같습니다.
- 투사체를 생성한다.
- 투사체를 움직인다.
- 투사체가 계속 남아있지 않게 일정 시간이 지난 뒤 투사체를 없앤다.
투사체 생성
지금까지 저희가 게임 오브젝트를 사용할 때는 전부 게임 실행 전에 직접 화면에 배치했었습니다.
하지만 투사체는 게임을 실행하는 도중 생성되어 날아가야 하며, 키 입력에 따라 여러 개가 생길 필요도 있습니다.
이러한 오브젝트를 위해 유니티에서는 프리팹(Prefab)이라는 에셋 타입을 이용합니다.
프리팹을 만드는 법은 간단합니다.
하이어라키 창에서 원하는 오브젝트를 드래그 해 프로젝트 창의 Assets 폴더에 넣으면 프리팹이 됩니다.
(저는 프리팹의 관리를 쉽게 하기 위해, Assets 폴더에 Prefabs 폴더를 생성해 그 안에 넣었습니다.)
이렇게 생성된 프리팹은 파란색 큐브 아이콘을 가지게 됩니다.
위의 방법대로 Bullet 프리팹을 만든 뒤, 더블클릭하여 프리팹 모드로 들어가 봅시다.
프리팹 모드로 들어가면 씬 뷰, 하이어라키 뷰, 인스펙터 뷰가 해당 프리팹에 맞춰 변경되게 됩니다.
인스펙터 뷰에서 Sprite Renderer 컴포넌트를 추가한 뒤 Knob 스프라이트를 씌워 간단한 투사체를 만들었습니다.
프리팹 모드에서 나가려면, 하이어라키 창 왼쪽 위의 뒤로 가기 버튼을 누르면 됩니다.
프리팹 모드에서 나간 뒤, PlayerController에 위와 같은 코드를 추가해 줍니다.
Input.GetKey() 대신 Input.GetKeyDown()이 쓰인 것을 알 수 있는데, GetKeyDown은 GetKey와 달리, 키가 눌리는 순간 그 한 번만을 체크하는 메서드입니다.
또한 Instantiate() 메서드는 인수로 전달된 프리팹 게임 오브젝트를 게임에 생성해 줍니다.
그런데 위에 적은 코드를 보면, 변수를 선언만 했을 뿐 어떠한 값을 담거나 하지 않았습니다.
그럼 어떻게 Instantiate() 메서드가 생성해야 할 오브젝트를 알 수 있을까요?
답은 플레이어 오브젝트의 인스펙터 창을 보면 나옵니다.
speed 변수가 그랬듯, public으로 선언한 BulletPrefab 변수도 인스펙터 창에서 확인할 수 있습니다.
우리가 여기에서 값에 변화를 주면, 코드에서도 해당 값으로 인식하고 작동하게 됩니다.
그러니 우리가 만든 프리팹 게임 오브젝트를 직접 넣어주도록 합시다.
이때, 프로젝트 창에 있는 BulletPrefab을 넣어야 하며, 하이어라키 창의 BulletPrefab을 넣으면 안 되니 주의합시다.
그 후 프로젝트를 실행해 스페이스바를 몇 번 눌러보면, 하이어라키 창을 통해 무사히 Bullet 오브젝트가 생성되는 것을 알 수 있습니다.
마지막으로 Bullet의 위치를 생성 직후 플레이어의 위치로 옮겨주는 것으로 투사체 생성은 마무리입니다.
투사체 발사
투사체를 만드는 것에는 성공했으니 이제 투사체에 속도를 주어 투사체를 움직여봅시다.
게임 오브젝트에 속도를 주는 대표적인 방법으로는 리지드바디 2D(Rigidbody2D) 컴포넌트를 추가하는 것이 있습니다.
리지드바디2D 컴포넌트는 해당 오브젝트를 유니티 물리엔진이 제어하게 만드는 컴포넌트로, 중력을 적용하는 등의 작업은 리지드바디2D 컴포넌트를 오브젝트에 추가하는 것만으로 끝날 절도로 유용한 컴포넌트입니다.
이제 Bullet 프리팹의 프리팹 모드로 들어간 뒤 리지드바디2D 컴포넌트를 추가하면 되는데, 앞서 말했듯이 리지드바디는 중력을 적용해 주는 역할도 합니다. 직선으로 날아가야 할 총알에 중력이 적용되는 건 우리가 바라는 바가 아니므로, 컴포넌트의 옵션 중에서 중력 스케일을 0으로 바꿔두는 것을 잊지 맙시다.
리지드바디 컴포넌트를 추가했다면, PlayerController 스크립트로 돌아와 투사체를 생성하는 부분에 속도를 주는 코드를 추가해 봅시다.
GetComponent() 메서드는 <> 안에 적힌 것과 같은 이름을 가진 컴포넌트에 접근하는 메서드이고, AddForce() 메서드는 Vector를 입력받아 해당 오브젝트에 입력받은 방향과 세기로 힘을 가하는 메서드입니다.
해당 코드를 입력한 뒤 실행하면 총알이 플레이어 오브젝트에서 생성된 뒤 아주 느리게 위로 향하는 것을 볼 수 있습니다.
플레이어의 속도를 조절할 때 했던 것처럼 BulletSpeed 변수를 선언한 뒤, AddForce 메서드 속 Vector2.up에 곱해줍시다.
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerController : MonoBehaviour { public float speed = 0.05f; public float BulletSpeed; public GameObject BulletPrefab; void Update() { if(Input.GetKey(KeyCode.W)){ this.transform.Translate(0, speed, 0); } if(Input.GetKey(KeyCode.A)){ this.transform.Translate(-speed, 0, 0); } if(Input.GetKey(KeyCode.S)){ this.transform.Translate(0, -speed, 0); } if(Input.GetKey(KeyCode.D)){ this.transform.Translate(speed, 0, 0); } if(Input.GetKeyDown(KeyCode.Space)){ GameObject Bullet = Instantiate(BulletPrefab); Bullet.transform.position = transform.position; Bullet.GetComponent<Rigidbody2D>().AddForce(Vector2.up * BulletSpeed); } } }
완성하면 위와 같은 코드가 나오겠죠.
BulletSpeed 또한 public으로 선언했으므로, 인스펙터 창에서 확인, 수정할 수 있습니다.
100을 입력한 뒤 다시 한번 게임을 실행해 투사체를 발사해 보면, 아까와는 다르게 확연한 속도로 투사체가 움직이는 것을 확인할 수 있습니다.
투사체 없애기
지금 상태대로라면, 게임 실행 도중 생성된 투사체는 설령 화면을 벗어난다고 하더라도 사라지지 않고 게임을 종료할 때까지 계속 한 방향으로 날아가게 될 것입니다.
이를 막기 위해 투사체가 발사된 뒤 일정 시간이 지나면 투사체가 소멸되도록 해야 합니다.
오브젝트의 소멸은 Destroy() 메서드를 사용하면 되는데, 그렇다고 그냥 그대로 Start()나 Update() 메서드에 넣어버리면 오브젝트가 생성되자마자 소멸될 것입니다.
즉, 오브젝트가 생성된 이후 일정 시간이 지났을 때 Destroy()를 실행해야 하는데, 이때 사용하는 것이 바로 Invoke() 메서드입니다.
Invoke() 메서드는 두 개의 인수를 갖는데, 첫 번째는 실행하고자 하는 함수 이름이고, 두 번째는 해당 함수를 몇 초 후에 실행할지입니다.
일단 Bullet 프리팹의 프리팹 모드로 들어가, Bullet이라는 이름의 스크립트를 만들어 부착해 줍시다.
(스크립트도 늘어나기 시작했으므로, Assets 폴더 안에 Scripts 폴더를 만들어 스크립트를 모아두었습니다.)
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Bullet : MonoBehaviour { void Start() { Invoke("DestroySelf", 2.0f); } void DestroySelf() { Destroy(gameObject); } }
그 후 위와 같이 코드를 작성해 주면, Invoke() 메서드가 실행된 지 2초 후에 DestroySelf라는 이름을 가진 함수를 실행하게 되어, 스스로 소멸하게 됩니다. 한번 테스트해봅시다.
'프로그래밍' 카테고리의 다른 글
[Unity]유니티 입문하기 6-4(객체 지향 언어란?) (0) 2023.08.04 [Unity]유니티 입문하기 6-3 번외(한번에 투사체 여러개 발사하기) (0) 2023.08.03 [Unity]유니티 입문하기 6-2(키 입력, 이동 구현) (0) 2023.08.02 [Unity]유니티 입문하기 6-1(오브젝트 활성화/비활성화, 위치 조정) (0) 2023.08.01 [Unity]유니티 입문하기 5-5(C# 기초개념 - 제어문) (0) 2023.07.28