PJ/Assets/scripts/dotfs_scripts/LevelGenerator.cs

136 lines
4.7 KiB
C#
Raw Permalink Normal View History

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
}
}