136 lines
4.7 KiB
C#
136 lines
4.7 KiB
C#
|
|
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<GameObject> 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<DifficultyTier> difficultyTiers;
|
|||
|
|
|
|||
|
|
[Header("Pool Settings")]
|
|||
|
|
private Queue<Chunk> activeChunks = new Queue<Chunk>();
|
|||
|
|
private Dictionary<int, Queue<Chunk>> pool = new Dictionary<int, Queue<Chunk>>();
|
|||
|
|
|
|||
|
|
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<Chunk>();
|
|||
|
|
|
|||
|
|
if (pool[id].Count > 0)
|
|||
|
|
{
|
|||
|
|
Chunk chunk = pool[id].Dequeue();
|
|||
|
|
chunk.gameObject.SetActive(true);
|
|||
|
|
return chunk;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return Instantiate(prefab).GetComponent<Chunk>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
private void RecycleChunk(Chunk chunk)
|
|||
|
|
{
|
|||
|
|
chunk.gameObject.SetActive(false);
|
|||
|
|
// Мы не знаем ID префаба здесь напрямую в этой упрощенной версии,
|
|||
|
|
// в идеале хранить ID в скрипте Chunk. Для примера просто Destroy:
|
|||
|
|
Destroy(chunk.gameObject);
|
|||
|
|
// Примечание: Для полноценного пулинга добавьте int prefabID в класс Chunk
|
|||
|
|
}
|
|||
|
|
}
|