using UnityEngine; // 발판으로서 필요한 동작을 담은 스크립트 public class Platform : MonoBehaviour { public GameObject[] obstacles; // 장애물 오브젝트들 public int emptyPatternWeight = 2; // 장애물이 없는 패턴이 선택될 가중치 public Sprite mileageSprite; // 이 발판에서 사용할 마일리지 토큰 스프라이트 public int mileagePatternChance = 50; // 마일리지 패턴 등장 확률 public int smallMileageValue = 10; // 일반 토큰 가치 public int bonusMileageValue = 30; // 어려운 루트 보너스 토큰 가치 private bool stepped = false; // 플레이어 캐릭터가 밟았었는가 private MileagePickup[] mileagePickups; // 런타임에 생성하는 마일리지 토큰 풀 private const int MileagePoolSize = 5; // 컴포넌트가 활성화될때 마다 매번 실행되는 메서드 private void OnEnable() { // 발판을 리셋하는 처리 stepped = false; EnsureMileagePickups(); for(int i = 0; i < obstacles.Length; i++) { obstacles[i].SetActive(false); } HideMileagePickups(); if(obstacles.Length == 0) { TryPlaceMileagePattern(null); return; } // 낮은 장애물과 높은 장애물이 동시에 켜져 불가능한 배치가 되지 않도록 하나만 선택한다. int patternIndex = Random.Range(0, obstacles.Length + emptyPatternWeight); GameObject activeObstacle = null; if(patternIndex < obstacles.Length) { activeObstacle = obstacles[patternIndex]; activeObstacle.SetActive(true); } TryPlaceMileagePattern(activeObstacle); } void OnCollisionEnter2D(Collision2D collision) { // 플레이어 캐릭터가 자신을 밟았을때 점수를 추가하는 처리 if(collision.collider.tag == "Player" && !stepped) { stepped = true; GameManager.instance.AddScore(1); } } private void EnsureMileagePickups() { if(mileagePickups != null && mileagePickups.Length == MileagePoolSize) { return; } mileagePickups = new MileagePickup[MileagePoolSize]; for(int i = 0; i < MileagePoolSize; i++) { GameObject pickupObject = new GameObject("Mileage Pickup " + (i + 1)); pickupObject.transform.SetParent(transform); pickupObject.transform.localScale = Vector3.one; SpriteRenderer spriteRenderer = pickupObject.AddComponent(); spriteRenderer.sprite = mileageSprite; spriteRenderer.sortingLayerName = "Foreground"; spriteRenderer.sortingOrder = 1; CircleCollider2D pickupCollider = pickupObject.AddComponent(); pickupCollider.isTrigger = true; pickupCollider.radius = 0.35f; mileagePickups[i] = pickupObject.AddComponent(); mileagePickups[i].Setup(mileageSprite, smallMileageValue); pickupObject.SetActive(false); } } private void HideMileagePickups() { if(mileagePickups == null) { return; } for(int i = 0; i < mileagePickups.Length; i++) { if(mileagePickups[i] != null) { mileagePickups[i].gameObject.SetActive(false); } } } private void TryPlaceMileagePattern(GameObject activeObstacle) { if(mileageSprite == null || mileagePickups == null || Random.Range(0, 100) >= mileagePatternChance) { return; } if(activeObstacle == null) { PlaceSafeMileageLine(); return; } if(activeObstacle.name.Contains("Slide")) { PlaceSlideMileageLine(); } else { PlaceJumpMileageArc(activeObstacle.transform.localPosition.x); } } private void PlaceSafeMileageLine() { Vector2[] positions = { new Vector2(-2f, 2.25f), new Vector2(-1f, 2.25f), new Vector2(0f, 2.25f), new Vector2(1f, 2.25f), new Vector2(2f, 2.25f) }; PlaceMileageTokens(positions, smallMileageValue); } private void PlaceJumpMileageArc(float obstacleX) { Vector2[] positions = { new Vector2(obstacleX - 1.2f, 2.7f), new Vector2(obstacleX, 3.45f), new Vector2(obstacleX + 1.2f, 2.7f), new Vector2(obstacleX + 1.9f, 2.25f) }; PlaceMileageTokens(positions, smallMileageValue); SetPickupValue(1, bonusMileageValue); } private void PlaceSlideMileageLine() { Vector2[] positions = { new Vector2(-1.5f, 1.45f), new Vector2(-0.5f, 1.45f), new Vector2(0.5f, 1.45f), new Vector2(1.5f, 1.45f) }; PlaceMileageTokens(positions, smallMileageValue); SetPickupValue(2, bonusMileageValue); } private void PlaceMileageTokens(Vector2[] positions, int value) { int count = Mathf.Min(positions.Length, mileagePickups.Length); for(int i = 0; i < count; i++) { mileagePickups[i].Setup(mileageSprite, value); mileagePickups[i].transform.localPosition = positions[i]; mileagePickups[i].ResetPickup(); } } private void SetPickupValue(int index, int value) { if(index < 0 || index >= mileagePickups.Length || !mileagePickups[index].gameObject.activeSelf) { return; } mileagePickups[index].Setup(mileageSprite, value); } }