using System; using UnityEngine; using Random = UnityEngine.Random; // 발판을 생성하고 주기적으로 재배치하는 스크립트 public class PlatformSpawner : MonoBehaviour { [Serializable] public class TutorialStep { public Platform.PlatformPattern platformPattern; public Platform.MileagePattern mileagePattern; public float yPosition; public string message; } public GameObject platformPrefab; // 생성할 발판의 원본 프리팹 public int count = 3; // 생성할 발판의 개수 public bool tutorialMode = true; // 튜토리얼에서는 랜덤 대신 정해진 순서로 배치 public TutorialStep[] tutorialSteps; // 튜토리얼 발판 순서 public float timeBetSpawnMin = 1.25f; // 다음 배치까지의 시간 간격 최솟값 public float timeBetSpawnMax = 2.25f; // 다음 배치까지의 시간 간격 최댓값 public float tutorialSpawnInterval = 2.2f; // 튜토리얼 발판 배치 간격 private float timeBetSpawn; // 다음 배치까지의 시간 간격 public float yMin = -3.5f; // 배치할 위치의 최소 y값 public float yMax = 1.5f; // 배치할 위치의 최대 y값 private float xPos = 20f; // 배치할 위치의 x 값 private GameObject[] platforms; // 미리 생성한 발판들 private int currentIndex = 0; // 사용할 현재 순번의 발판 private int tutorialStepIndex = 0; // 진행 중인 튜토리얼 순번 private Vector2 poolPosition = new Vector2(0, -25); // 초반에 생성된 발판들을 화면 밖에 숨겨둘 위치 private float lastSpawnTime; // 마지막 배치 시점 void Start() { EnsureTutorialSteps(); // 변수들을 초기화하고 사용할 발판들을 미리 생성 platforms = new GameObject[count]; for(int i = 0; i < count; i++) { platforms[i] = Instantiate(platformPrefab, poolPosition, Quaternion.identity); } // 마지막 배치 시점 초기화 lastSpawnTime = 0f; // 다음번 배치까지의 시간 간격을 0으로 초기화 timeBetSpawn = 0f; } void Update() { // 순서를 돌아가며 주기적으로 발판을 배치 if(GameManager.instance.isGameover) { return; } if(Time.time >= lastSpawnTime + timeBetSpawn) { lastSpawnTime = Time.time; timeBetSpawn = tutorialMode ? tutorialSpawnInterval : Random.Range(timeBetSpawnMin, timeBetSpawnMax); float yPos = tutorialMode ? GetTutorialYPosition() : Random.Range(yMin, yMax); platforms[currentIndex].SetActive(false); ConfigurePlatform(platforms[currentIndex]); platforms[currentIndex].SetActive(true); platforms[currentIndex].transform.position = new Vector2(xPos, yPos); currentIndex++; if(currentIndex >= count) { currentIndex = 0; } if(tutorialMode) { tutorialStepIndex++; } } } private void ConfigurePlatform(GameObject platformObject) { Platform platform = platformObject.GetComponent(); if(platform == null) { return; } if(!tutorialMode) { platform.ConfigureForRandom(); return; } TutorialStep step = GetCurrentTutorialStep(); platform.ConfigureForTutorial(step.platformPattern, step.mileagePattern); if(GameManager.instance != null) { GameManager.instance.SetTutorialMessage(step.message); } } private float GetTutorialYPosition() { return Mathf.Clamp(GetCurrentTutorialStep().yPosition, yMin, yMax); } private TutorialStep GetCurrentTutorialStep() { EnsureTutorialSteps(); if(tutorialStepIndex < tutorialSteps.Length) { return tutorialSteps[tutorialStepIndex]; } int reviewStartIndex = Mathf.Max(0, tutorialSteps.Length - 3); int reviewLength = tutorialSteps.Length - reviewStartIndex; int reviewIndex = reviewStartIndex + ((tutorialStepIndex - tutorialSteps.Length) % reviewLength); return tutorialSteps[reviewIndex]; } private void EnsureTutorialSteps() { if(tutorialSteps != null && tutorialSteps.Length > 0) { return; } tutorialSteps = new TutorialStep[] { CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, -2.4f, "Tutorial 1: Run forward and collect mileage."), CreateStep(Platform.PlatformPattern.LowMid, Platform.MileagePattern.JumpArc, -2.4f, "Tutorial 2: Left click to jump over suitcase obstacles."), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, -2.4f, "Tutorial 3: Hold right click to slide under airport signs."), CreateStep(Platform.PlatformPattern.LowLeft, Platform.MileagePattern.JumpArc, -2.1f, "Tutorial 4: Suitcases mean jump."), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, -2.2f, "Tutorial 5: Hanging signs mean slide."), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, -1.8f, "Tutorial complete: collect mileage and keep moving."), }; } private TutorialStep CreateStep(Platform.PlatformPattern platformPattern, Platform.MileagePattern mileagePattern, float yPosition, string message) { TutorialStep step = new TutorialStep(); step.platformPattern = platformPattern; step.mileagePattern = mileagePattern; step.yPosition = yPosition; step.message = message; return step; } }