using UnityEngine; using System.Collections.Generic; public class LevelGenerator : MonoBehaviour { [System.Serializable] public struct DifficultyTier { [Range(0, 1)] public float startPercentage; // Начало этапа (0.0 = 0%) public List chunkPrefabs; // Префабы для этого этапа public Vector3 gravityValue; } [Header("Settings")] [SerializeField] private Transform playerTransform; [SerializeField] private int totalChunksLimit = 50; // Лимит уровня [SerializeField] private int initialChunks = 4; // Сколько спавним сразу [SerializeField] private float spawnDistance = 20f; // Дистанция до последнего чанка для спавна нового [SerializeField] private List difficultyTiers; [Header("Pool Settings")] private Queue activeChunks = new Queue(); private Dictionary> pool = new Dictionary>(); private Vector3 nextSpawnPoint; private int chunksSpawned = 0; void Start() { UpdateWorldGravity(); // Начальная точка — позиция генератора nextSpawnPoint = transform.position; for (int i = 0; i < initialChunks; i++) { SpawnNextChunk(); } } private void UpdateWorldGravity() { float progress = (float)chunksSpawned / totalChunksLimit; Vector3 targetGravity = difficultyTiers[0].gravityValue; // Ищем гравитацию текущего тира (аналогично логике выбора префабов) foreach (var tier in difficultyTiers) { if (progress >= tier.startPercentage) { targetGravity = tier.gravityValue; } } // Применяем гравитацию Physics2D.gravity = targetGravity; Debug.Log($"Current Gravity: {Physics.gravity} | Progress: {progress}"); } void Update() { // Проверяем расстояние до последнего чанка if (chunksSpawned < totalChunksLimit) { float distanceToLast = Vector3.Distance(playerTransform.position, nextSpawnPoint); if (distanceToLast < spawnDistance) { SpawnNextChunk(); } } // Очистка старых чанков (удаляем, если игрок ушел далеко) if (activeChunks.Count > 0) { Chunk oldest = activeChunks.Peek(); // Расстояние берем с запасом, чтобы чанк не исчез на глазах if (Vector3.Distance(playerTransform.position, oldest.transform.position) > spawnDistance * 2) { RecycleChunk(activeChunks.Dequeue()); } } } private void SpawnNextChunk() { UpdateWorldGravity(); GameObject prefab = GetRandomPrefabByProgress(); Chunk chunk = GetChunkFromPool(prefab); chunk.AlignTo(nextSpawnPoint); nextSpawnPoint = chunk.exit.position; activeChunks.Enqueue(chunk); chunksSpawned++; } private GameObject GetRandomPrefabByProgress() { float progress = (float)chunksSpawned / totalChunksLimit; DifficultyTier currentTier = difficultyTiers[0]; // Ищем подходящий тир сложности по прогрессу foreach (var tier in difficultyTiers) { if (progress >= tier.startPercentage) currentTier = tier; } return currentTier.chunkPrefabs[Random.Range(0, currentTier.chunkPrefabs.Count)]; } // --- Логика Object Pooling --- private Chunk GetChunkFromPool(GameObject prefab) { int id = prefab.GetInstanceID(); if (!pool.ContainsKey(id)) pool[id] = new Queue(); if (pool[id].Count > 0) { Chunk chunk = pool[id].Dequeue(); chunk.gameObject.SetActive(true); return chunk; } return Instantiate(prefab).GetComponent(); } private void RecycleChunk(Chunk chunk) { chunk.gameObject.SetActive(false); // Мы не знаем ID префаба здесь напрямую в этой упрощенной версии, // в идеале хранить ID в скрипте Chunk. Для примера просто Destroy: Destroy(chunk.gameObject); // Примечание: Для полноценного пулинга добавьте int prefabID в класс Chunk } }