
오늘 한 것


모델링은 이렇게 5개
처음에는 장애물에 모델링만 입혔었는데 기둥이 하나만 나오는게 이상해서
길게 나오도록 바꿔보았다.
여기서는 캐릭터가 크지만 실제 캐릭터 모델링은 작기 때문에
그 크기에 맞춘 것임
장애물 모델링을 프로젝트 창에 이동 후
전에 만들었던 장애물과 똑같은 방법으로 제작.
그리고 다시 프리팹화 시킴

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;
public class Obstacle : MonoBehaviour
{
[SerializeField] private GameObject[] obstaclePrefab; // 장애물 프리팹 넣기
[SerializeField] private GameObject[] longObstaclePrefab; // 장애물이 한 줄에 길게 나옴
[Header("장애물 생성 설정")] private float[] spawnXPosition = { -2.6f, 0.1f, 2.6f }; // 장애물 가로 간격
public float spawnYPosition; // 높이
public float spawnZPosition; // 화면 뒷부분
public float minSpawnDelay; // 장애물 소환되는데 걸리는 최소 시간
public float maxSpawnDelay; // 장애물 소환되는데 걸리는 최대 시간
[Header("긴 장애물 설정")] public float obstacleCount; // 한 번에 몇 개씩 나오게 할 건지
public float betweenObstacle; // 길게 장애물이 나올 때 장애물간 간격 (겹치기 방지)
private float LongSpawnDelay; // 긴 장애물 소환되는데 걸리는 시간
void Start()
{
// 레인 별 독립적으로 장애물 소환
for (int i = 0; i < spawnXPosition.Length; i++)
{
// 코루틴 무한 반복
StartCoroutine(SpawnObstacle(i));
}
}
IEnumerator SpawnObstacle(int laneIdx) // 장애물 소환 (여기서 소환 처리)
{
while (true)
{
// 장애물 소환되는 시간 간격
yield return new WaitForSeconds(Random.Range(minSpawnDelay, maxSpawnDelay));
// 장애물 타입
float obstacleType = Random.Range(1, 101);
if (obstacleType <= 70) // 일반 장애물 소환 - 70% 확률로 소환
{
yield return StartCoroutine(RandomSpawnObstacle(laneIdx));
}
else // 긴 장애물 소환 - 30% 확률로 소환
{
yield return StartCoroutine(RandomSpawnLongObstacle(laneIdx));
}
}
}
IEnumerator RandomSpawnObstacle(int laneIdx) // 랜덤으로 일반 장애물 소환
{
// 장애물 모델링 중 하나를 랜덤으로 선택
int randObstaclePrefabs = Random.Range(0, obstaclePrefab.Length);
// 위 코드에서 뽑힌 장애물을 선택된 장애물로 지정
GameObject selectedObstaclePrefab = obstaclePrefab[randObstaclePrefabs];
// 장애물 생성 x좌표 가져오기 - 레인 별로 독립적으로 장애물 소환
float spawnX = spawnXPosition[laneIdx];
// 장애물 소환 위치 - 장애물 모델링이 90도 돌아간 상태여서 인스펙터에서 설정한 값으로 불러옴
GameObject newObstacle = Instantiate(selectedObstaclePrefab,
new Vector3(spawnX, spawnYPosition, spawnZPosition), selectedObstaclePrefab.transform.rotation);
// 장애물 오브젝트들이 ObstacleSpawner 오브젝트의 안에 생성됨
// 생성된 장애물 오브젝트들이 ObstacleSpawner를 부모 오브젝트로 설정 - hierarchy 창을 정리하는 용도
newObstacle.transform.parent = this.transform;
yield break; // 코루틴 종료
}
IEnumerator RandomSpawnLongObstacle(int laneIdx) // 랜덤으로 긴 장애물 소환
{
for (int i = 0; i < obstacleCount; i++) // 장애물을 연속으로 생성하는 조건문
{
// 장애물 모델링 중 하나를 랜덤으로 선택
int randObstaclePrefabs = Random.Range(0, longObstaclePrefab.Length);
// 위 코드에서 뽑힌 장애물을 선택된 장애물로 지정
GameObject selectedObstaclePrefabs = longObstaclePrefab[randObstaclePrefabs];
// 장애물 생성 x좌표 가져오기 - 레인 별로 독립적으로 장애물 소환
float spawnX = spawnXPosition[laneIdx];
// 장애물 소환 위치 - 장애물 모델링이 90도 돌아간 상태여서 인스펙터에서 설정한 값으로 불러옴
GameObject newObstacle = Instantiate(selectedObstaclePrefabs,
new Vector3(spawnX, spawnYPosition, spawnZPosition), selectedObstaclePrefabs.transform.rotation);
// 장애물 오브젝트들이 ObstacleSpawner 오브젝트의 안에 생성됨
// 생성된 장애물 오브젝트들이 ObstacleSpawner를 부모 오브젝트로 설정 - hierarchy 창을 정리하는 용도
newObstacle.transform.parent = this.transform;
// 각 장애물 사이의 간격을 조절
ObstacleMove obstacleMove = newObstacle.GetComponent<ObstacleMove>();
// 소환 시간 = 거리 / 속도
float LongSpawnDelay = betweenObstacle / obstacleMove.obstacleSpeed;
if (i < obstacleCount - 1)
{
// 장애물이 하나씩 나오는데 걸리는 시간
yield return new WaitForSeconds(LongSpawnDelay);
}
}
}
}
긴 장애물을 만들 때 RandomSpawnObstacle(), RandomSpawnLongObstacle()
이렇게 두 개로 나누고 start()에 랜덤 값과 if문을 추가하여
0이면 일반 장애물, 1이면 긴 장애물이 소환되도록 했다.
플레이 하니 긴 장애물과 일반 장애물이 겹쳐서 나오는 현상이 발생했다.
둘 중에 하나만 나오게 하고 싶었는데
장애물이 길어서 다 나오기 전에 소환된 것 같다.
해결 방안:
SpawnObstacle()을 만들어서 하나만 나오도록 통제하도록 하였다.
yield return new WaitForSeconds(Random.Range(minSpawnDelay, maxSpawnDelay)); 를
제일 위에 적어서 확실하게 일정 시간동안 멈췄다가 함수를 나가고,
다시 호출 되면 yield 이후부터 코드가 실행되어
둘 중 하나만 실행 되도록 수정하였다.