PJ/Assets/scripts/dotfs_scripts/LevelGenerator.cs

136 lines
No EOL
4.7 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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