using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; // 발판을 생성하고 주기적으로 재배치하는 스크립트 public class PlatformSpawner : MonoBehaviour { private class PendingTutorialGuide { public Transform target; public GameManager.TutorialGuideType guideType; public string title; public string message; public float triggerX; } public GameObject platformPrefab; // 계속 이어지는 기본 발판 프리팹 public GameObject jumpObstaclePrefab; // 낮은 점프 장애물 프리팹 public GameObject slideObstaclePrefab; // 위쪽 슬라이딩 장애물 프리팹 public int count = 12; // 기본 발판 풀 개수 public bool usePatternCourse = true; // 검증된 발판 패턴 코스를 사용 public bool tutorialMode = true; // 처음에는 튜토리얼 패턴을 먼저 배치 public CourseStep[] tutorialSteps; // 튜토리얼 발판 순서 public CourseStep[] stagePatternSteps; // 튜토리얼 이후 반복할 검증된 발판 순서 public bool keepWorldSpacingBySpeed = true; // 게임 속도가 빨라져도 발판 사이 실제 거리를 유지 public int continuousCoursePoolCount = 12; // 기본 발판을 촘촘히 깔 때 필요한 최소 풀 크기 public int obstaclePoolCount = 6; // 점프/슬라이드 장애물별 재사용 풀 크기 public float timeBetSpawnMin = 1.25f; // 다음 배치까지의 시간 간격 최솟값 public float timeBetSpawnMax = 2.25f; // 다음 배치까지의 시간 간격 최댓값 public float tutorialSpawnInterval = 2.2f; // 튜토리얼 발판 배치 간격 private float timeBetSpawn; // 다음 배치까지의 시간 간격 private const float FallbackGroundY = -2.4f; private const float FallbackBasicSpacing = 0.58f; private const float FallbackActionSpacing = 0.72f; private const float FallbackLandingSpacing = 0.64f; private const float FallbackAerialSpacing = 2.05f; public float yMin = -3.5f; // 배치할 위치의 최소 y값 public float yMax = 1.5f; // 배치할 위치의 최대 y값 public float tutorialGuideTriggerX = 5f; // 발판/장애물이 이 위치까지 오면 설명을 띄운다. private float xPos = 20f; // 배치할 위치의 x 값 private GameObject[] platforms; // 기본 발판 풀 private GameObject[] jumpObstacles; // 점프 장애물 풀 private GameObject[] slideObstacles; // 슬라이드 장애물 풀 private int platformIndex = 0; // 기본 발판 풀 순번 private int jumpObstacleIndex = 0; // 점프 장애물 풀 순번 private int slideObstacleIndex = 0; // 슬라이드 장애물 풀 순번 private int courseStepIndex = 0; // 진행 중인 패턴 코스 순번 private Platform.PlatformSkin mapPlatformSkin = Platform.PlatformSkin.Airport; // 현재 맵에서 사용할 발판 스킨 private readonly List pendingTutorialGuides = new List(); // 실제 체험 직전에 띄울 설명들 private GameObject activeFinishLandingPlatform; // 도착 게이트가 공중에 뜨지 않도록 깔아두는 전용 발판 private bool courseSpawningStopped = false; // 도착 게이트 뒤로 새 발판/장애물이 나오지 않게 막는다. private Vector2 poolPosition = new Vector2(0, -25); // 초반에 생성된 발판들을 화면 밖에 숨겨둘 위치 private float lastSpawnTime; // 마지막 배치 시점 public void ApplyMap(MapDefinition mapDefinition) { if(mapDefinition == null) { return; } usePatternCourse = true; tutorialMode = mapDefinition.isTutorial; mapPlatformSkin = mapDefinition.platformSkin; tutorialSteps = CourseStepFactory.CloneSteps(mapDefinition.openingSteps); stagePatternSteps = CourseStepFactory.CloneSteps(mapDefinition.loopSteps); courseStepIndex = 0; courseSpawningStopped = false; pendingTutorialGuides.Clear(); ClearFinishLandingPlatform(); ResetPoolIndices(); lastSpawnTime = Time.time; timeBetSpawn = 0f; count = Mathf.Max(count, continuousCoursePoolCount); EnsurePlatformPool(); DeactivateAllPlatformPools(); } public void SpawnFinishLandingPlatform(float spawnX, float groundY) { if(platformPrefab == null) { return; } ClearFinishLandingPlatform(); activeFinishLandingPlatform = Instantiate(platformPrefab, poolPosition, Quaternion.identity); activeFinishLandingPlatform.SetActive(false); CourseStep landingStep = CreateStep( Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, Mathf.Clamp(groundY, yMin, yMax), FallbackLandingSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Basic); ConfigurePlatform(activeFinishLandingPlatform, landingStep); activeFinishLandingPlatform.transform.position = new Vector2(spawnX, landingStep.yPosition); activeFinishLandingPlatform.SetActive(true); } public void ClearFinishLandingPlatform() { if(activeFinishLandingPlatform != null) { Destroy(activeFinishLandingPlatform); activeFinishLandingPlatform = null; } } public void StopCourseSpawningAfterFinishGate() { courseSpawningStopped = true; pendingTutorialGuides.Clear(); } void Start() { EnsurePatternSteps(); if(usePatternCourse && tutorialMode) { count = Mathf.Max(count, continuousCoursePoolCount); } // 변수들을 초기화하고 사용할 발판들을 미리 생성 EnsurePlatformPool(); // 마지막 배치 시점 초기화 lastSpawnTime = 0f; // 다음번 배치까지의 시간 간격을 0으로 초기화 timeBetSpawn = 0f; } private void EnsurePlatformPool() { int basicCount = usePatternCourse ? Mathf.Max(count, continuousCoursePoolCount) : Mathf.Max(1, count); int obstacleCount = Mathf.Max(1, obstaclePoolCount); EnsurePool(ref platforms, basicCount, platformPrefab); EnsurePool(ref jumpObstacles, obstacleCount, jumpObstaclePrefab); EnsurePool(ref slideObstacles, obstacleCount, slideObstaclePrefab); count = platforms != null ? platforms.Length : count; } private void EnsurePool(ref GameObject[] pool, int requiredCount, GameObject prefab) { if(prefab == null) { return; } if(pool != null && pool.Length >= requiredCount) { return; } GameObject[] nextPool = new GameObject[requiredCount]; if(pool != null) { for(int i = 0; i < pool.Length; i++) { nextPool[i] = pool[i]; } } for(int i = 0; i < nextPool.Length; i++) { if(nextPool[i] == null) { nextPool[i] = Instantiate(prefab, poolPosition, Quaternion.identity); nextPool[i].SetActive(false); } } pool = nextPool; } private void ResetPoolIndices() { platformIndex = 0; jumpObstacleIndex = 0; slideObstacleIndex = 0; } private void DeactivateAllPlatformPools() { DeactivatePool(platforms); DeactivatePool(jumpObstacles); DeactivatePool(slideObstacles); } private void DeactivatePool(GameObject[] pool) { if(pool == null) { return; } for(int i = 0; i < pool.Length; i++) { if(pool[i] != null) { pool[i].SetActive(false); pool[i].transform.position = poolPosition; } } } void Update() { // 순서를 돌아가며 주기적으로 발판을 배치 if(GameManager.instance == null || GameManager.instance.isGameover || !GameFlowManager.IsGameplayActive) { return; } if(courseSpawningStopped) { return; } UpdatePendingTutorialGuides(); if(GameManager.instance != null && GameManager.instance.IsTutorialGuidePaused) { return; } EnsurePlatformPool(); if(Time.time >= lastSpawnTime + timeBetSpawn) { lastSpawnTime = Time.time; CourseStep step = usePatternCourse ? GetCurrentCourseStep() : null; timeBetSpawn = step != null ? GetStepSpawnInterval(step) : Random.Range(timeBetSpawnMin, timeBetSpawnMax); float yPos = step != null ? Mathf.Clamp(step.yPosition, yMin, yMax) : Random.Range(yMin, yMax); GameObject platformObject = TakeFromPool(platforms, ref platformIndex); if(platformObject == null) { return; } platformObject.SetActive(false); ConfigurePlatform(platformObject, step); platformObject.SetActive(true); platformObject.transform.position = new Vector2(xPos, yPos); SpawnCourseObstacles(step, yPos); RegisterTutorialGuide(platformObject.transform, step); if(usePatternCourse) { courseStepIndex++; } } } private void UpdatePendingTutorialGuides() { if(GameManager.instance == null || pendingTutorialGuides.Count == 0 || GameManager.instance.IsTutorialGuidePaused) { return; } for(int i = 0; i < pendingTutorialGuides.Count; i++) { PendingTutorialGuide guide = pendingTutorialGuides[i]; if(guide == null || guide.target == null || !guide.target.gameObject.activeInHierarchy) { pendingTutorialGuides.RemoveAt(i); i--; continue; } if(guide.target.position.x <= guide.triggerX) { GameManager.instance.SetTutorialGuide(guide.guideType, guide.title, guide.message); pendingTutorialGuides.RemoveAt(i); return; } } } private void RegisterTutorialGuide(Transform target, CourseStep step) { if(target == null || step == null || step.guideType == GameManager.TutorialGuideType.None || (string.IsNullOrEmpty(step.title) && string.IsNullOrEmpty(step.message))) { return; } pendingTutorialGuides.Add(new PendingTutorialGuide { target = target, guideType = step.guideType, title = step.title, message = step.message, triggerX = GetTutorialGuideTriggerX(step) }); } private float GetTutorialGuideTriggerX(CourseStep step) { if(step != null && step.guideType == GameManager.TutorialGuideType.DoubleJump) { return -2f; } return tutorialGuideTriggerX; } private void SpawnCourseObstacles(CourseStep step, float yPos) { if(step == null) { return; } if(step.coursePlatformType == CoursePlatformType.ForceHit || step.platformPattern == Platform.PlatformPattern.ForceHit) { SpawnJumpObstacle(Platform.PlatformPattern.LowMid, yPos); return; } if(step.coursePlatformType == CoursePlatformType.Jump || IsJumpPattern(step.platformPattern)) { Platform.PlatformPattern jumpPattern = IsJumpPattern(step.platformPattern) ? step.platformPattern : Platform.PlatformPattern.LowMid; SpawnJumpObstacle(jumpPattern, yPos); return; } if(step.coursePlatformType == CoursePlatformType.Slide || step.platformPattern == Platform.PlatformPattern.Slide) { SpawnSlideObstacle(step.slideLayout, yPos); } } private void SpawnJumpObstacle(Platform.PlatformPattern platformPattern, float yPos) { GameObject obstacleObject = TakeFromPool(jumpObstacles, ref jumpObstacleIndex); if(obstacleObject == null) { return; } obstacleObject.SetActive(false); ConfigureObstacle(obstacleObject, platformPattern, SlideObstaclePattern.SlideLayout.Random); obstacleObject.transform.position = new Vector2(xPos, yPos); obstacleObject.SetActive(true); } private void SpawnSlideObstacle(SlideObstaclePattern.SlideLayout slideLayout, float yPos) { GameObject obstacleObject = TakeFromPool(slideObstacles, ref slideObstacleIndex); if(obstacleObject == null) { return; } obstacleObject.SetActive(false); ConfigureObstacle(obstacleObject, Platform.PlatformPattern.Slide, slideLayout); obstacleObject.transform.position = new Vector2(xPos, yPos); obstacleObject.SetActive(true); } private void ConfigureObstacle( GameObject obstacleObject, Platform.PlatformPattern platformPattern, SlideObstaclePattern.SlideLayout slideLayout) { CourseObstacle obstacle = obstacleObject.GetComponent(); if(obstacle != null) { obstacle.Configure(mapPlatformSkin, platformPattern, slideLayout); } } private bool IsJumpPattern(Platform.PlatformPattern platformPattern) { return platformPattern == Platform.PlatformPattern.LowLeft || platformPattern == Platform.PlatformPattern.LowMid || platformPattern == Platform.PlatformPattern.LowRight; } private GameObject TakeFromPool(GameObject[] pool, ref int poolIndex) { if(pool == null || pool.Length == 0) { return null; } if(poolIndex < 0 || poolIndex >= pool.Length) { poolIndex = 0; } GameObject platformObject = pool[poolIndex]; poolIndex++; if(poolIndex >= pool.Length) { poolIndex = 0; } return platformObject; } private void ConfigurePlatform(GameObject platformObject, CourseStep step) { Platform platform = platformObject.GetComponent(); if(platform == null) { return; } if(step == null) { platform.ConfigureForRandom(mapPlatformSkin); return; } platform.ConfigureForTutorial(step.mileagePattern, step.itemPattern, mapPlatformSkin); // 설명은 발판 생성 시점이 아니라 실제 체험 직전에 RegisterTutorialGuide가 띄운다. } private float GetStepSpawnInterval(CourseStep step) { float spawnInterval; if(step != null && step.spawnInterval > 0f) { spawnInterval = step.spawnInterval; } else { spawnInterval = tutorialSpawnInterval; } if(keepWorldSpacingBySpeed && GameManager.instance != null) { spawnInterval /= Mathf.Max(0.1f, GameManager.instance.gameSpeed); } return Mathf.Max(0.05f, spawnInterval); } private CourseStep GetCurrentCourseStep() { EnsurePatternSteps(); if(tutorialMode && courseStepIndex < tutorialSteps.Length) { return tutorialSteps[courseStepIndex]; } int loopIndex = tutorialMode ? courseStepIndex - tutorialSteps.Length : courseStepIndex; if(stagePatternSteps == null || stagePatternSteps.Length == 0) { return CreateStep( Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, -2.2f, tutorialSpawnInterval, "", ""); } loopIndex %= stagePatternSteps.Length; if(loopIndex < 0) { loopIndex += stagePatternSteps.Length; } return stagePatternSteps[loopIndex]; } private void EnsurePatternSteps() { EnsureTutorialSteps(); EnsureStagePatternSteps(); } private void EnsureTutorialSteps() { if(tutorialSteps != null && tutorialSteps.Length > 0) { return; } tutorialSteps = new CourseStep[] { CreateTutorialStep(CourseStepKind.Jump, Platform.PlatformPattern.LowMid, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(CourseStepKind.DoubleJumpTakeoff, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackAerialSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(CourseStepKind.Slide, Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.CenterPair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(CourseStepKind.ForceHit, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.HealthItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing, Platform.ItemPattern.HealthSushi), CreateTutorialStep(CourseStepKind.InvincibleItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.InvincibleRamen), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), CreateTutorialStep(CourseStepKind.ShieldItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.Shield), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.MileageCardItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.MileageCard), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(CourseStepKind.SpeedItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.SpeedShoes), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), CreateTutorialStep(CourseStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), }; } private void EnsureStagePatternSteps() { if(stagePatternSteps != null && stagePatternSteps.Length > 0) { return; } stagePatternSteps = new CourseStep[] { CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackBasicSpacing, "", ""), CreateStep(Platform.PlatformPattern.LowMid, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Jump), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackLandingSpacing, "", ""), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.WidePair, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Slide), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackBasicSpacing, "", ""), CreateStep(Platform.PlatformPattern.LowLeft, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Jump), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.LeftPair, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Slide), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackBasicSpacing, "", ""), CreateStep(Platform.PlatformPattern.LowRight, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Jump), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackAerialSpacing, "", ""), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.RightPair, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Slide), CreateStep(Platform.PlatformPattern.LowMid, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Jump), CreateStep(Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackBasicSpacing, "", ""), CreateStep(Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.CenterPair, GameManager.TutorialGuideType.None, FallbackGroundY, FallbackActionSpacing, "", "", Platform.ItemPattern.None, CoursePlatformType.Slide), }; } private CourseStep CreateStep( Platform.PlatformPattern platformPattern, Platform.MileagePattern mileagePattern, SlideObstaclePattern.SlideLayout slideLayout, GameManager.TutorialGuideType guideType, float yPosition, float spawnInterval, string title, string message, Platform.ItemPattern itemPattern = Platform.ItemPattern.None, CoursePlatformType coursePlatformType = CoursePlatformType.Basic) { CourseStep step = new CourseStep(); step.coursePlatformType = coursePlatformType; step.platformPattern = platformPattern; step.mileagePattern = mileagePattern; step.slideLayout = slideLayout; step.itemPattern = itemPattern; step.guideType = guideType; step.yPosition = yPosition; step.spawnInterval = spawnInterval; step.title = title; step.message = message; return step; } private CourseStep CreateTutorialStep( CourseStepKind stepKind, Platform.PlatformPattern platformPattern, Platform.MileagePattern mileagePattern, SlideObstaclePattern.SlideLayout slideLayout, float yPosition, float spawnInterval, Platform.ItemPattern itemPattern = Platform.ItemPattern.None) { GameManager.TutorialGuideType guideType = GameManager.TutorialGuideType.None; string title = ""; string message = ""; switch(stepKind) { case CourseStepKind.Jump: guideType = GameManager.TutorialGuideType.Jump; title = "점프"; message = "가방 장애물이 보이면 왼쪽 클릭으로 뛰어넘습니다."; break; case CourseStepKind.DoubleJumpTakeoff: guideType = GameManager.TutorialGuideType.DoubleJump; title = "2단 점프"; message = "다음 발판이 멀리 있으면 공중에서 한 번 더 왼쪽 클릭합니다."; break; case CourseStepKind.Slide: guideType = GameManager.TutorialGuideType.Slide; title = "슬라이드"; message = "천장 표지판이 보이면 오른쪽 클릭을 누르고 지나갑니다."; break; case CourseStepKind.ForceHit: guideType = GameManager.TutorialGuideType.Damage; title = "피격"; message = "이번 구간은 일부러 맞아 목숨과 속도 감소를 확인합니다."; break; case CourseStepKind.HealthItem: guideType = GameManager.TutorialGuideType.Items; title = "초밥"; message = "초밥을 먹으면 잃은 목숨을 1 회복합니다."; break; case CourseStepKind.InvincibleItem: guideType = GameManager.TutorialGuideType.Items; title = "라멘"; message = "라멘을 먹고 다음 충돌을 피해 없이 지나가 봅니다."; break; case CourseStepKind.ShieldItem: guideType = GameManager.TutorialGuideType.Items; title = "방어막"; message = "방어막을 먹고 다음 충돌 1회를 막아 봅니다."; break; case CourseStepKind.SpeedItem: guideType = GameManager.TutorialGuideType.Items; title = "운동화"; message = "운동화는 속도를 회복해 일정이 늦어지는 것을 줄입니다."; break; case CourseStepKind.MileageCardItem: guideType = GameManager.TutorialGuideType.Items; title = "마일리지 카드"; message = "카드를 먹은 뒤 마일리지를 모으면 획득량이 늘어납니다."; break; } return CreateStep( platformPattern, mileagePattern, slideLayout, guideType, yPosition, spawnInterval, title, message, itemPattern, GetCoursePlatformType(stepKind, platformPattern, yPosition)); } private CoursePlatformType GetCoursePlatformType(CourseStepKind stepKind, Platform.PlatformPattern platformPattern, float yPosition) { if(stepKind == CourseStepKind.ForceHit || platformPattern == Platform.PlatformPattern.ForceHit) { return CoursePlatformType.ForceHit; } if(stepKind == CourseStepKind.Slide || platformPattern == Platform.PlatformPattern.Slide) { return CoursePlatformType.Slide; } if(stepKind == CourseStepKind.Jump || platformPattern == Platform.PlatformPattern.LowLeft || platformPattern == Platform.PlatformPattern.LowMid || platformPattern == Platform.PlatformPattern.LowRight) { return CoursePlatformType.Jump; } return CoursePlatformType.Basic; } }