Top.Mail.Ru
Ответы
Аватар пользователя
Аватар пользователя
Аватар пользователя
Аватар пользователя
Unity
+4

Помогите со скриптом на Unity (C#, Unity Engine)

Сделал скрипт для прорисовки чанков в 2d мире. Вроде всё работает без костылей, но лагает. Проверьте скрипт, может чего лишнего добавил(

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class ChunkLoader : MonoBehaviour

{

[System.Serializable]

public class ChunkInfo

{

public Vector2Int coord; // Координаты чанка

public GameObject prefab; // Префаб чанка

}

[Header("Основные настройки")]

public Transform loadingTarget; // Цель отслеживания (игрок)

public float chunkWidth = 50f; // Ширина чанка

public float chunkHeight = 25f; // Высота чанка

public int loadRadius = 1; // Радиус загрузки

[Header("База префабов")]

public List<ChunkInfo> chunkDatabase = new List<ChunkInfo>(); // Только указанные вами чанки

public Transform chunksParent; // Родитель для чанков

private Dictionary<Vector2Int, GameObject> activeChunks = new Dictionary<Vector2Int, GameObject>();

private Vector2Int lastPlayerChunk;

private bool isProcessing = false;

void Start()

{

if (!loadingTarget && Camera.main != null)

loadingTarget = Camera.main.transform;

if (loadingTarget == null)

{

Debug.LogError("Не назначен объект для отслеживания!");

return;

}

// Первоначальная загрузка чанков

lastPlayerChunk = CalculatePlayerChunk();

LoadInitialChunks();

}

void LoadInitialChunks()

{

// Загружаем все чанки в начальном радиусе

for (int x = -loadRadius; x <= loadRadius; x++)

{

for (int y = -loadRadius; y <= loadRadius; y++)

{

Vector2Int coord = new Vector2Int(

lastPlayerChunk.x + x,

lastPlayerChunk.y + y

);

TryLoadChunk(coord);

}

}

}

void Update()

{

if (loadingTarget == null) return;

Vector2Int currentChunk = CalculatePlayerChunk();

// Обновляем только при смене чанка

if (currentChunk != lastPlayerChunk && !isProcessing)

{

lastPlayerChunk = currentChunk;

StartCoroutine(UpdateChunks());

}

}

IEnumerator UpdateChunks()

{

isProcessing = true;

// 1. Определяем необходимые координаты

HashSet<Vector2Int> neededCoords = new HashSet<Vector2Int>();

for (int x = -loadRadius; x <= loadRadius; x++)

{

for (int y = -loadRadius; y <= loadRadius; y++)

{

neededCoords.Add(new Vector2Int(

lastPlayerChunk.x + x,

lastPlayerChunk.y + y

));

}

}

// 2. Удаляем чанки вне зоны видимости

List<Vector2Int> toRemove = new List<Vector2Int>();

foreach (var coord in activeChunks.Keys)

{

if (!neededCoords.Contains(coord))

{

Destroy(activeChunks[coord]);

toRemove.Add(coord);

}

}

foreach (var coord in toRemove) activeChunks.Remove(coord);

// 3. Загружаем новые чанки (только из базы данных)

foreach (var coord in neededCoords)

{

if (!activeChunks.ContainsKey(coord))

{

TryLoadChunk(coord);

yield return null; // Пауза между загрузкой чанков

}

}

isProcessing = false;

}

void TryLoadChunk(Vector2Int coord)

{

// Ищем префаб в базе данных

foreach (var info in chunkDatabase)

{

if (info.coord == coord)

{

// Создаем чанк

Vector3 position = new Vector3(

coord.x * chunkWidth,

coord.y * chunkHeight,

0

);

GameObject newChunk = Instantiate(info.prefab, position, Quaternion.identity);

if (chunksParent) newChunk.transform.SetParent(chunksParent);

newChunk.name = $"Chunk_{coord.x}_{coord.y}";

activeChunks.Add(coord, newChunk);

break; // Прекращаем поиск после нахождения

}

}

}

Vector2Int CalculatePlayerChunk()

{

Vector3 pos = loadingTarget.position;

return new Vector2Int(

Mathf.RoundToInt(pos.x / chunkWidth),

Mathf.RoundToInt(pos.y / chunkHeight)

);

}

}

По дате
По рейтингу
Аватар пользователя
Новичок
3нед

Ответ от RawMind AI Инструкция по оптимизации скрипта ChunkLoader: 1. Замена списка на словарь для базы данных Переведите `chunkDatabase` из списка в словарь, чтобы ускорить поиск префабов: ```csharp // Вместо List<ChunkInfo> используйте Dictionary<Vector2Int, GameObject> public Dictionary<Vector2Int, GameObject> chunkDatabase = new Dictionary<Vector2Int, GameObject>(); ``` Почему: Поиск по словарю происходит за O(1), а не O(n). Это ускорит метод `TryLoadChunk()`. 2. Удаление пауз в загрузке чанков Уберите `yield return null;` из цикла загрузки новых чанков: ```csharp // В IEnumerator UpdateChunks() foreach (var coord in neededCoords) { if (!activeChunks.ContainsKey(coord)) { TryLoadChunk(coord); // Удалить yield return null; } } ``` Почему: Каждый `yield` добавляет задержку на кадр. Для 9 чанков это 9 лишних кадров. 3. Оптимизация удаления ненужных чанков Используйте `ToList()` для итерации по ключам словаря: ```csharp // В IEnumerator UpdateChunks()