01 반복문을 이용한 오브젝트 생성
✅ 반복문을 이용해 원하는 개수만큼 오브젝트 생성
- 반복문 내부의 변수 'i'를 위치, 회전 값 연산에 활용
- 중첩 반복문을 이용해 격자 형태로 오브젝트 생성
📌 변수 i 활용 예제 코드
→ 10개의 복제된 게임 오브젝트가 생성
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private GameObject boxPrefab; private void Awake() { for (int i = 0; i < 10; ++i) { Vector3 position = new Vector3(-4.5f + i, 0, 0); Quaternion rotation = Quaternion.Euler(0, 0, i * 10); Instantiate(boxPrefab, position, rotation); } } }
i를 활용하여 10개의 복제된 오브젝트에 대해 위치와 회전값에 변화를 주니 아래와 같이 10개의 복제된 오브젝트가 생성된 것을 볼 수 있었다.
📌 중첩 반복문 활용 예제 코드
→ 격자 형태 오브젝트 생성 가능
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private GameObject boxPrefab; private void Awake() { for (int y = 0; y < 10; ++y) { for (int x = 0; x < 10; ++x) { Vector3 position = new Vector3(-4.5f + x, 4.5f - y, 0); Instantiate(boxPrefab, position, Quaternion.identity); } } } }
중첩 반복문을 활용하여 코드를 작성 후 게임을 실행시켜보면 아래와 같이 격자 형태로 오브젝트가 생성된 것을 볼 수 있다.
📌 반복문 내부에 조건문을 활용하여 특정 위치에 오브젝트 생성하지 않는 예제 코드
▶ continue 키워드
: 반복문에서 현재 반복을 건너띄고 증감 연산으로 이동한다. 예를 들어, y, x가 모두 0일 때 오브젝트를 생성하지 않고, ++x로 이동해서 계속 반복문을 실행한다.
1. 기본 구조
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private GameObject boxPrefab; private void Awake() { for (int y = 0; y < 10; ++y) { for (int x = 0; x < 10; ++x) { if ( x == y ) { continue; } Vector3 position = new Vector3(-4.5f + x, 4.5f - y, 0); Instantiate(boxPrefab, position, Quaternion.identity); } } } }
▶ 기본 구조 코드 실행 결과
2. OR 연산 활용 continue 구문 실행
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private GameObject boxPrefab; private void Awake() { for (int y = 0; y < 10; ++y) { for (int x = 0; x < 10; ++x) { if ( x == y || x + y == 9) { continue; } Vector3 position = new Vector3(-4.5f + x, 4.5f - y, 0); Instantiate(boxPrefab, position, Quaternion.identity); } } } }
▶ OR 연산 활용 코드 실행 결과
02 임의의 프리팹으로 오브젝트 생성
✅ 배열 변수를 이용해 여러 개의 프리팹을 등록하고 활용
→ Random.Range() 메소드를 이용해 0부터 프리팹의 개수 (prefabArray.Length)에서 임의의 숫자를 뽑아내 그 숫자에 해당하는 프리팹을 생성
📌 예제 코드
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private GameObject[] prefabArray; private void Awake() { for (int i = 0; i < 10; ++i) { int index = Random.Range(0, prefabArray.Length); Vector3 position = new Vector3(-4.5f + i, 0, 0); Instantiate(prefabArray[index], position, Quaternion.identity); } } }
코드 설명)
▶ int result = Random.Range int min, int max);
: min ~ max-1 사이의 정수 중 임의의 정수를 result에 반환
▶ float result = Random.Range (float min, float max);
: min ~ max-1 사이의 실수 중 임의의 실수를 result에 반환
위와 같이 코드를 작성한 후, Prefab Array를 3으로 설정하고 각각의 요소에 Project View에 있는 프리팹 즉, Box, Circle, Triangle을 등록해준다.
이후 게임을 실행해보면 10개가 생성되는데 랜덤 값을 사용하기 때문에 매번 실행할 때마다 생성 결과가 다른 것을 확인할 수 있다.
03 임의의 위치에서 오브젝트 생성
✅ 임의의 위치에서 원하는 개수만큼 오브젝트 생성→ Random.Range() 메소드를 이용해 오브젝트의 생성 위치를 임의로 설정
📌 예제 코드
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private int objectSpawnCount = 30; [SerializeField] private GameObject[] prefabArray; private void Awake() { for (int i = 0; i < objectSpawnCount; ++i) { int index = Random.Range(0, prefabArray.Length); float x = Random.Range(-7.5f, 7.5f); // x 위치 float y = Random.Range(-4.5f, 4.5f); // y 위치 Vector3 position = new Vector3(x, y, 0); Instantiate(prefabArray[index], position, Quaternion.identity); } } }
위 스크립트 코드에 대해 게임 실행 결과, 아래와 같이 오브젝트들이 화면 내에서 랜덤하게 생성되는 것을 볼 수 있다.
만약 생성되는 오브젝트의 개수 즉, Object Spawn Count 값을 늘린다면 아래와 같이 개수가 50개로 늘어나서 생성된 것을 확인할 수 있다.
04 SpawnPoint에서 오브젝트 생성
✅ 맵에 배치된 오브젝트의 위치에서 오브젝트 생성
📌 예제 코드
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private int objectSpawnCount = 30; [SerializeField] private GameObject[] prefabArray; [SerializeField] private Transform[] spawnPointArray; private void Awake() { for (int i = 0; i < objectSpawnCount; ++i) { int prefabIndex = Random.Range(0, prefabArray.Length); int spawnIndex = Random.Range(0, spawnPointArray.Length); Vector3 position = spawnPointArray[spawnIndex].position; GameObject clone = Instantiate(prefabArray[prefabIndex], position, Quaternion.identity); } } }
게임 실행 결과, Object Spawn Count의 값인 30만큼 게임 오브젝트들이 생성된 것을 알 수 있었다. 이때, 각각의 게임 오브젝트들이 모두 겹쳐보여서 30개가 티가 나지 않지만, 하나하나 자리를 이동해보면 각각 크기, 모양이 다른 30개의 오브젝트가 생성되어 있다.
위 실습을 통해 생성한 30개의 오브젝트들이 이동을 할 수 있도록 코드를 작성해보자.
📌 예제 코드
[ ObjectSpawner.cs ]
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private int objectSpawnCount = 30; [SerializeField] private GameObject[] prefabArray; [SerializeField] private Transform[] spawnPointArray; private void Awake() { for (int i = 0; i < objectSpawnCount; ++i) { int prefabIndex = Random.Range(0, prefabArray.Length); int spawnIndex = Random.Range(0, spawnPointArray.Length); Vector3 position = spawnPointArray[spawnIndex].position; GameObject clone = Instantiate(prefabArray[prefabIndex], position, Quaternion.identity); Vector3 moveDirection = (spawnIndex == 0 ? Vector3.right : Vector3.left); clone.GetComponent<Movement2D>().Setup(moveDirection); } } }
▶ 삼항연산자) D = A ? B : C;
→ A의 조건문이 참이면 B를 D에 저장하고, 거짓이면 C를 D에 저장
[ Movement2D.cs ]
using UnityEngine; public class Movement2D : MonoBehaviour { private float moveSpeed = 5.0f; // 이동 속도 private Vector3 moveDirection; public void Setup(Vector3 direction) // 이동 방향 { moveDirection = direction; } private void Update() { transform.position += moveDirection * moveSpeed * Time.deltaTime; } }
코드 작성 후, 각 프리팹 오브젝트에 Movement2D 스크립트를 컴포넌트에 추가해준다.
게임을 실행하면 아래와 같은 결과를 볼 수 있다. 보기에는 위, 아래로 2개의 오브젝트만 이동하는 것처럼 보이지만 복제된 30개의 게임 오브젝트가 함께 이동하기 때문에 실행을 멈추고 각 오브젝트들의 위치를 변경해보면 모두 합쳐져있는 것을 볼 수 있다.
다음으로 오브젝트가 생성되는 시간을 조절하여 하나씩 생성되도록 코드를 수정해보자.
📌 ObjectSpawner.cs 코드 수정
using UnityEngine; public class ObjectSpawner : MonoBehaviour { [SerializeField] private int objectSpawnCount = 30; [SerializeField] private GameObject[] prefabArray; [SerializeField] private Transform[] spawnPointArray; private int currentObjectCount = 0; private float objectSpawnTime = 0.0f; private void Update() { if (currentObjectCount +1 > objectSpawnCount) { return; } objectSpawnTime += Time.deltaTime; if (objectSpawnTime >= 0.5f) { int prefabIndex = Random.Range(0, prefabArray.Length); int spawnIndex = Random.Range(0, spawnPointArray.Length); Vector3 position = spawnPointArray[spawnIndex].position; GameObject clone = Instantiate(prefabArray[prefabIndex], position, Quaternion.identity); Vector3 moveDirection = (spawnIndex == 0 ? Vector3.right : Vector3.left); clone.GetComponent<Movement2D>().Setup(moveDirection); currentObjectCount++; // 현재 생성된 오브젝트의 개수를 1 증가시킨다. objectSpawnTime = 0.0f; // 시간을 0으로 초기화 해야 다시 0.5초를 계산할 수 있다. } } }
▶ 코드 수정 시, Awake 함수는 게임이 시작되자마자 1회만 호출되기 때문에 오브젝트가 한꺼번에 생성될 것이다. 따라서 우리는 해당 코드를 Update 함수로 변경하여 우리가 원하는 조건이 만족될 때 한번씩만 오브젝트를 생성할 수 있도록 조건문을 작성해줄 수 있다.
게임을 실행해보면, 아래와 같이 게임 오브젝트가 0.5초마다 하나씩 생성되는데 어느 위치에서 어떤 오브젝트가 생성될지는 아무도 모르는 즉, 랜덤으로 생성된다.
05 플레이어 위치에서 오브젝트 생성
우선 실습을 위해 새로운 2D 오브젝트를 생성하여 Player 이미지를 Sprite에 넣어준다.
플레이어 이동을 위한 PlayControlller.cs 코드를 아래와 같이 작성할 수 있다.
📌 예제 코드
using UnityEngine; public class PlayerController : MonoBehaviour { [SerializeField] private KeyCode keyCodeFire = KeyCode.Space; [SerializeField] private GameObject bulletPrefab; private float moveSpeed = 3.0f; private void Update() { float x = Input.GetAxisRaw("Horizontal"); float y = Input.GetAxisRaw("Vertical"); transform.position += new Vector3(x, y, 0) * moveSpeed * Time.deltaTime; if (Input.GetKeyDown(keyCodeFire)) { GameObject clone = Instantiate(bulletPrefab, transform.position, Quaternion.identity); clone.name = "Bullet"; clone.transform.localScale = Vector3.one * 0.5f; clone.GetComponent<SpriteRenderer>().color = Color.red; } } }
이후 플레이어 게임 오브젝트에 스크립트 코드를 컴포넌트로 삽입하고 플레이어를 이동시킬 키 코드를 Space가 아닌 다른 값으로도 변경시켜줄 수 있다.
게임을 실행시켜보니 아래와 같이 오브젝트를 이동하면서 스페이스바를 누를 때마다 빨간색 총알이 나오는 것을 볼 수 있다.
하지만, 총알은 제자리에 머물러 있다. 따라서 총알이 움직일 수 있도록 추가적으로 코드를 수정해보자.
📌 예제 코드 수정
using UnityEngine; public class PlayerController : MonoBehaviour { [SerializeField] private KeyCode keyCodeFire = KeyCode.Space; [SerializeField] private GameObject bulletPrefab; private float moveSpeed = 3.0f; private Vector3 lastMoveDirection = Vector3.right; private void Update() { float x = Input.GetAxisRaw("Horizontal"); float y = Input.GetAxisRaw("Vertical"); transform.position += new Vector3(x, y, 0) * moveSpeed * Time.deltaTime; if (x != 0 || y != 0) { lastMoveDirection = new Vector3(x, y, 0); } if (Input.GetKeyDown(keyCodeFire)) { GameObject clone = Instantiate(bulletPrefab, transform.position, Quaternion.identity); clone.name = "Bullet"; clone.transform.localScale = Vector3.one * 0.5f; clone.GetComponent<SpriteRenderer>().color = Color.red; clone.GetComponent<Movement2D>().Setup(lastMoveDirection); } } }
코드 수정 후, 게임을 실행해보니 아래와 같이 총알이 작동하는 것을 볼 수 있었다. 처음에는 초기 설정 값이었던 오른쪽으로 총알이 나가고, 이후에는 가장 마지막에 움직인 방향으로 총알이 나가는 것을 확인할 수 있다.
출처 : 따라하면서 배우는 고박사의 유니티 기초(https://inf.run/sgcy)
'Study > Unity' 카테고리의 다른 글
[Unity 2D Basic] 플랫폼 게임에서의 플레이어 이동, 점프 구현 (0) | 2024.05.01 |
---|---|
[Unity 2D Basic] 게임오브젝트 삭제 함수 (0) | 2024.04.16 |
[Unity 2D Basic] 게임 오브젝트 생성 함수 (0) | 2024.04.16 |
[Unity 2D Basic] 게임 오브젝트 물리와 충돌 (0) | 2024.04.10 |
[Unity 2D Basic] 게임 오브젝트 이동 (0) | 2024.04.10 |