게임 내의 오브젝트를 복제해서 새로운 적을 생성하면 안 되는 이유?
게임 내에 원본으로 사용 중인 적이 사라졌을 시, 복사할 원본이 없어서 에러가 발생할 수 있다.
따라서 원본 오브젝트는 파일로 보관하여 사용하는 방식, 즉 프리팹을 이용해야 한다.
프리팹(Prefab)이란?
게임(Hierarchy View)에 존재하는 게임오브젝트를 Project View에 파일로 저장해둔 것
프리팹(Prefab) 생성
1. 원하는 형태로 게임 오브젝트를 꾸민다.
2. Hierarchy View의 게임오브젝트를 Project View로 드래그&드롭한다.
3. Hierarchy View에 있는 게임오브젝트를 삭제한다.
게임오브젝트 복제 방법
게임오브젝트 복제 : Instantiate(원본 게임오브젝트)
Instantiate(GameObject original);
original 게임오브젝트(프리팹)를 복제해서 생성하는 코드로
복제되는 오브젝트의 모든 컴포넌트 정보는 원본과 완전히 동일하다.
<ObjectSpawner 코드>
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
[SerializeField]
private GameObject character;
private void Awake()
{
Instantiate(character);
}
}
위와 같이 코드를 작성한 후 새로운 Sprite를 생성한 후 작성한 코드를 Inspector창에 입력한 뒤 Character에 생성한 프리팹을 넣어준다.
위치, 회전을 추가한 복제 : Instantiate(원본, 위치, 회전)
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
[SerializeField]
private GameObject character;
private void Awake()
{
Instantiate(character, new Vector3(3, 3, 0), Quaternion.identity);
Instantiate(character, new Vector3(-1, -2, 0), Quaternion.identity);
}
}
위의 ObjectSpawner 코드를 다음과 같이 변경하면 복제된 게임오브젝트의 위치를 설정할 수 있다.
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
[SerializeField]
private GameObject character;
private void Awake()
{
Quaternion rotation = Quaternion.Euler(0, 0, 45);
Instantiate(character, new Vector3(-1, -2, 0), rotation);
}
}
복제된 게임오브젝트를 회전시키기 위해선 다음과 같이 코드를 작성하면 된다.
오일러(Euler)는 우리가 알고 있는 0~360도의 각도를 표현하는 방식
쿼터니온(Quaternion)은 사원수로 3개의 벡터 요소와 하나의 스칼라 요소로 구성하는 방식이다.
Instantiate의 회전 변수에 들어가는 정보는 쿼터니온 방식으로 각도를 표현하는데, 이는 특정 각도로 입력하는 것이 어렵다는 단점이 있다. 따라서
Quaternion rotation = Quaternion.Euler(0, 0, 45);
Quaternion.Euler(0, 0, 45)와 같이 오일러 방식을 쿼터니온 방식으로 변경해주는 코드를 이용한다.
복제 정보를 통한 복제 : GameObject clone = instantiate()
using UnityEngine;
public class ObjectSpawner : MonoBehaviour
{
[SerializeField]
private GameObject character;
private void Awake()
{
Quaternion rotation = Quaternion.Euler(0, 0, 45);
GameObject clone = Instantiate(character, Vector3.zero, rotation);
clone.name = "Character001";
clone.GetComponent<SpriteRenderer>().color = Color.black;
clone.transform.position = new Vector3(2, 1, 0);
clone.transform.localScale = new Vector3(3, 2, 1);
}
}
Instantiate() 활용 예제1
다음 코드는 입력한 Box Prefab에 대해 왼쪽에서부터 오른쪽으로 10개의 Box를 회전시키며 복제하는 코드이다.
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);
}
}
}
해당 코드를 통해 다음 이미지와 같은 결과를 얻을 수 있다.
Instantiate() 활용 예제2
다음 코드는 입력한 3개(Box, Circle, Triangle)의 Prefab에 대해 왼쪽에서부터 오른쪽으로 10개의 Random 생성된 도형을 복제하는 코드이다.
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 index = Random.Range(0, prefabArray.Length);
위 코드는 Random.Range(int min, int max); 이용한 것으로 min부터 max-1까지 정수 중에서 임의의 숫자를 가져오게 된다.
해당 코드를 통해 다음 이미지와 같은 결과를 얻을 수 있다.
Instantiate() 활용 예제3
다음 코드는 화면에 입력한 3개(Box, Circle, Triangle)의 Prefab에 대해 랜덤으로 30개의 도형을 랜덤 위치에 복제하는 코드이다.
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);
float y = Random.Range(-4.5f, 4.5f);
Vector3 position = new Vector3(x, y, 0);
Instantiate(prefabArray[index], position, Quaternion.identity);
}
}
}
해당 코드를 통해 다음 이미지와 같은 결과를 얻을 수 있다.
Instantiate() 활용 예제4
다음 코드는 2개의 Spawn 지점에서 랜덤한 Prefab이 생성되어 지정된 방향으로 움직이는 코드이다.
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 코드
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()
{
// objectSpawnCount 개수만큼만 생성하고 더이상 생성하지 않도록 하기 위해 설정
if (currentObjectCount + 1 > objectSpawnCount)
{
return;
}
// deltaTime만을 덧셈으로 활용하면 실체 시간과 동일하게 흘러감
objectSpawnTime += Time.deltaTime;
// 0.5초마다 한 번씩 실행
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++;
objectSpawnTime = 0.0f;
}
}
}
ObjectSpawner 코드
에러 없이 코드를 실행하기 위해서는 Movement2D 코드를 이용하려는 모든 Prefab의 Inspector에 추가해야 한다.
해당 코드를 통해 다음 이미지와 같은 결과를 얻을 수 있다.
'게임 > Unity' 카테고리의 다른 글
Unity 2D ) 게임오브젝트 삭제 함수 Destroy() (0) | 2021.03.04 |
---|---|
Unity 2D) 게임오브젝트 물리와 충돌 (0) | 2021.02.28 |
Unity 2D) 게임오브젝트 이동 (0) | 2021.02.27 |
Unity 이벤트 함수 (0) | 2021.02.27 |
Unity 콘솔뷰에 데이터 출력 (0) | 2021.01.15 |