런게임에 배치되어있는 장애물들에 대해 스크립트를 작성해볼 것이다
목표 : 도로들이 뒤로 이동할때, 장애물도 생성되고 같이 이동하고 interactZone에 닿으면 장애물이 다시 맨 뒤 도로로 이동
Obstacle 스크립트 (위치 지정)도로들이 뒤로 계속 이동할때, 장애물들을 리스트에 저장해두고, 리스트에 들어있는 장애물들을 동적으로 생성하게 한다
장애물들이 도로에 배치되면, 배치된 오브젝트들은 리스트에서 비활성화하고 배치되지 않은 오브젝트들은 리스트에 들어있는 상태
현재 장애물 오브젝트의 위치값의 x축의 값을 (4 * 랜덤(-1, 0, 1))으로 설정하려고 했다
그리고 이 장애물과 장애물의 위치를 토대로 동적생성하도록 코드를 짬

위치값을 다 배열에 담아둘 것이다 → Vector3타입을 담을 수 있는 배열 생성
배열의 크기는 미리 3으로 잡아둔다
(-4, 0, 0) (0, 0, 0) (4, 0, 0)
위치 값 셋팅은 Awake()에서 작성
위의 스크립트가 값 셋팅이 더 좋은 거 같지만 확인을 위해 각 인덱스마다 위치값 셋팅
최종적으로 리스트에 들어있는 장애물 오브젝트 5개는 런타임 중 동적으로 생성되고(활성화 상태),
interactZone에 닿으면 장애물 오브젝트가 비활성화되고 다시 맨 뒤 도로로 이동 후 장애물이 활성화된다
→ 📌 장애물이 활성화 될때마다 새로운 랜덤위치에 생성되야하기 때문에 OnEnable()에 작성한다!
📌 OnEnable()은 스크립트가 활성화 될때마다 호출된다
Obstacle 전체 코드using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Obstacle : MonoBehaviour
{
[SerializeField] Vector3[] randomVector3 = new Vector3[3];
private void Awake()
{
randomVector3[0] = new Vector3(-4, 0, 0);
randomVector3[1] = new Vector3( 0, 0, 0);
randomVector3[2] = new Vector3( 4, 0, 0);
}
// 스크립트가 활성화 될때마다 호출
private void OnEnable()
{
transform.position = randomVector3[Random.Range(0, randomVector3.Length)];
}
}
Obstacle Manager 스크립트 (생성 & 관리)동적으로 생성된 장애물 게임 오브젝트를 담을 리스트 생성
Resources 폴더에 있는 장애물을 런 타임중에 가져와서 Instantiate를 사용하여 동적 생성한다
생성된 게임 오브젝트는 비활성화 상태로 리스트에 저장
코루틴을 사용하여 리스트에 저장된 게임 오브젝트들을 특정 시간 후에 활성화 되도록 한다
리스트에 넣을 타입을 잘못 지정했다 -> Obstacle 클래스 타입 x
생성된 게임 오브젝트를 담아야하니까 -> GameObject 타입 o
Resources 폴더에서 해당 장애물을 가져와야하는데, 그냥 리스트를 생성하고 에디터에서 장애물들을 할당해줬다
GameObject 타입을 담을 obstacles 리스트 생성
string 타입을 담을 obstacleNames 리스트 생성
→ Resources 폴더에 들어있는 장애물의 이름을 에디터에서 작성한다
obstacles 리스트의 Capacity 값을 10으로 할당한다
생성될 장애물의 갯수(5)만큼 반복하는데, obstacleManager 게임 오브젝트의 자식으로 들어갈 수 있게 위치를 gameObject.transform으로 지정하고, 생성될 장애물은 Resoures.Load(”경로이름”);을 통해 가져온다
📌 리스트이름.Add(데이터); : 를 통해 리스트에 데이터를 추가할 수 있다

리스트에 추가(Add) 하면 관리힙에 메모리를 할당한다
→ 계속 Add할때마다 새로운 크기의 메모리가 생성된다
→ 미리 리스트의 capacity값을 지정하자
리스트의 디폴트 기본 Capacity 크기는 4이다
리스트가 처음 생성될 때, 내부적으로 메모리가 4개의 요소를 저장할 수 있도록 크기4로 할당된다
→ 리스트에 요소를 추가하면서 이 크기를 초과하면 Capacity의 크기를 기존에서 2배로 늘린다
만약 5개의 요소를 리스트에 넣을 경우, 4개까지 요소를 넣고 5번째를 넣을때 capacity의 값은 8로 변경된다
→ 메모리 재할당 & 기존 값 복사 해서 넣기
→ 메모리 낭비
capacity값을 미리 지정해둘 경우→ 메모리 재할당을 최소화 한다

2.5f 마다 장애물 오브젝트를 활성화
만약 5개의 장애물이 모두 활성화 되었다면 코루틴 종료
리스트의 접근한 장애물이 이미 활성화된 상태라면 건너뛰고 다음 장애물 활성화
전체적인 동작은 비슷하게 짠 거 같은데.. 조금 잘못된 거 같아서 다시 짰다
while(true)문을 사용하여 반복한다
만약 현재 count가 리스트의 크기보다 커진다면 코루틴 종료 (모두 활성화 되었기 때문 - 순회 끝)
2.5초마다 해당 코드를 실행한다
랜덤 변수를 생성하고 0 ~ 5 중 랜덤하게 정수를 저장
만약 랜덤한 장애물 오브젝트가 활성화 상태라면 <<<<< random + 1로 다음 리스트 요소를 저장
장애물 게임 오브젝트 활성화
카운트 증가

using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
public class ObstacleManager : MonoBehaviour
{
// 동적으로 생성된 장애물 오브젝트를 담을 리스트
[SerializeField] List <GameObject> obstacles;
// Resources 폴더에 담긴 장애물의 이름을 담을 리스트
[SerializeField] List<string> obstacleNames;
// 생성될 장애물의 갯수
[SerializeField] int createCount = 5;
[SerializeField] int random;
void Start()
{
obstacles.Capacity = 10;
Create();
StartCoroutine(ActiveObstacle());
}
public void Create()
{
for(int i = 0; i < createCount; i++)
{
GameObject prefab =
Instantiate(Resources.Load<GameObject>(obstacleNames[Random.Range(0, obstacleNames.Count)]), gameObject.transform);
prefab.SetActive(false);
obstacles.Add(prefab);
}
}
IEnumerator ActiveObstacle()
{
int count = 0;
while(true)
{
if(count >= obstacles.Count)
{
yield break;
}
yield return new WaitForSeconds(2.5f);
random = Random.Range(0, obstacles.Count);
while (obstacles[random].activeSelf == true)
{
random = (random + 1) % obstacles.Count;
}
obstacles[random].SetActive(true);
count++;
}
}
}
QA 부문게임을 테스트해보고, 버그, 오류, 수정사항 등을 찾고 수정하는 일을 한다
게임 개발의 전 과정을 다양한 테스트를 진행하여 완성도를 높이는 일
성능 테스트. UI/UX 동작 잘 되는지, 버그 오류 발견, 호환성 테스트 등