using System; using System.Collections.Generic; using UnityEngine; using Random = UnityEngine.Random; // 발판을 생성하고 주기적으로 재배치하는 스크립트 public class PlatformSpawner : MonoBehaviour { public enum CoursePlatformType { Basic, Jump, Slide, ForceHit } private enum TutorialStepKind { None, Jump, DoubleJumpTakeoff, Slide, ForceHit, HealthItem, InvincibleItem, ShieldItem, SpeedItem, MileageCardItem } [Serializable] public class TutorialStep { public CoursePlatformType coursePlatformType; public Platform.PlatformPattern platformPattern; public Platform.MileagePattern mileagePattern; public SlideObstaclePattern.SlideLayout slideLayout; public Platform.ItemPattern itemPattern; public GameManager.TutorialGuideType guideType; public float yPosition; public float spawnInterval; public string title; public string message; } 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 TutorialStep[] tutorialSteps; // 튜토리얼 발판 순서 public TutorialStep[] 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 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 = MapDatabase.CloneSteps(mapDefinition.openingSteps); stagePatternSteps = MapDatabase.CloneSteps(mapDefinition.loopSteps); courseStepIndex = 0; pendingTutorialGuides.Clear(); ResetPoolIndices(); lastSpawnTime = Time.time; timeBetSpawn = 0f; count = Mathf.Max(count, continuousCoursePoolCount); EnsurePlatformPool(); DeactivateAllPlatformPools(); } 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; } UpdatePendingTutorialGuides(); if(GameManager.instance != null && GameManager.instance.IsTutorialGuidePaused) { return; } EnsurePlatformPool(); if(Time.time >= lastSpawnTime + timeBetSpawn) { lastSpawnTime = Time.time; TutorialStep 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, TutorialStep 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(TutorialStep step) { if(step != null && step.guideType == GameManager.TutorialGuideType.DoubleJump) { return -2f; } return tutorialGuideTriggerX; } private void SpawnCourseObstacles(TutorialStep step, float yPos) { if(step == null) { return; } if(step.coursePlatformType == CoursePlatformType.ForceHit || step.platformPattern == Platform.PlatformPattern.ForceHit) { SpawnJumpObstacle(Platform.PlatformPattern.LowMid, yPos); SpawnSlideObstacle(SlideObstaclePattern.SlideLayout.WidePair, 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, TutorialStep step) { Platform platform = platformObject.GetComponent(); if(platform == null) { return; } if(step == null) { platform.ConfigureForRandom(mapPlatformSkin); return; } platform.ConfigureForTutorial(Platform.PlatformPattern.Empty, step.mileagePattern, step.slideLayout, step.itemPattern, mapPlatformSkin); // 설명은 발판 생성 시점이 아니라 실제 체험 직전에 RegisterTutorialGuide가 띄운다. } private float GetStepSpawnInterval(TutorialStep 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 TutorialStep 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 TutorialStep[] { CreateTutorialStep(TutorialStepKind.Jump, Platform.PlatformPattern.LowMid, Platform.MileagePattern.JumpArc, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(TutorialStepKind.DoubleJumpTakeoff, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackAerialSpacing), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(TutorialStepKind.Slide, Platform.PlatformPattern.Slide, Platform.MileagePattern.SlideLine, SlideObstaclePattern.SlideLayout.CenterPair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing), CreateTutorialStep(TutorialStepKind.ForceHit, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(TutorialStepKind.HealthItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackLandingSpacing, Platform.ItemPattern.HealthSushi), CreateTutorialStep(TutorialStepKind.InvincibleItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.InvincibleRamen), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(TutorialStepKind.ShieldItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.Shield), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.ForceHit, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.WidePair, FallbackGroundY, FallbackActionSpacing), CreateTutorialStep(TutorialStepKind.SpeedItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.SpeedShoes), CreateTutorialStep(TutorialStepKind.MileageCardItem, Platform.PlatformPattern.Empty, Platform.MileagePattern.None, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing, Platform.ItemPattern.MileageCard), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), CreateTutorialStep(TutorialStepKind.None, Platform.PlatformPattern.Empty, Platform.MileagePattern.SafeLine, SlideObstaclePattern.SlideLayout.Random, FallbackGroundY, FallbackBasicSpacing), }; } private void EnsureStagePatternSteps() { if(stagePatternSteps != null && stagePatternSteps.Length > 0) { return; } stagePatternSteps = new TutorialStep[] { 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 TutorialStep 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) { TutorialStep step = new TutorialStep(); 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 TutorialStep CreateTutorialStep( TutorialStepKind 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 TutorialStepKind.Jump: guideType = GameManager.TutorialGuideType.Jump; title = "점프"; message = "가방 장애물이 보이면 왼쪽 클릭으로 뛰어넘습니다."; break; case TutorialStepKind.DoubleJumpTakeoff: guideType = GameManager.TutorialGuideType.DoubleJump; title = "2단 점프"; message = "다음 발판이 멀리 있으면 공중에서 한 번 더 왼쪽 클릭합니다."; break; case TutorialStepKind.Slide: guideType = GameManager.TutorialGuideType.Slide; title = "슬라이드"; message = "천장 표지판이 보이면 오른쪽 클릭을 누르고 지나갑니다."; break; case TutorialStepKind.ForceHit: guideType = GameManager.TutorialGuideType.Damage; title = "피격"; message = "이번 구간은 일부러 맞아 목숨과 속도 감소를 확인합니다."; break; case TutorialStepKind.HealthItem: guideType = GameManager.TutorialGuideType.Items; title = "초밥"; message = "초밥을 먹으면 잃은 목숨을 1 회복합니다."; break; case TutorialStepKind.InvincibleItem: guideType = GameManager.TutorialGuideType.Items; title = "라멘"; message = "라멘을 먹고 다음 충돌을 피해 없이 지나가 봅니다."; break; case TutorialStepKind.ShieldItem: guideType = GameManager.TutorialGuideType.Items; title = "방어막"; message = "방어막을 먹고 다음 충돌 1회를 막아 봅니다."; break; case TutorialStepKind.SpeedItem: guideType = GameManager.TutorialGuideType.Items; title = "운동화"; message = "운동화는 속도를 회복해 일정이 늦어지는 것을 줄입니다."; break; case TutorialStepKind.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(TutorialStepKind stepKind, Platform.PlatformPattern platformPattern, float yPosition) { if(stepKind == TutorialStepKind.ForceHit || platformPattern == Platform.PlatformPattern.ForceHit) { return CoursePlatformType.ForceHit; } if(stepKind == TutorialStepKind.Slide || platformPattern == Platform.PlatformPattern.Slide) { return CoursePlatformType.Slide; } if(stepKind == TutorialStepKind.Jump || platformPattern == Platform.PlatformPattern.LowLeft || platformPattern == Platform.PlatformPattern.LowMid || platformPattern == Platform.PlatformPattern.LowRight) { return CoursePlatformType.Jump; } return CoursePlatformType.Basic; } }