Я успешно реализовал оптимизацию для граничных и угловых кубов блоков. . Когда игрок запускает процесс генерации чанка, кубы на границах и углах, полностью закрытые со всех сторон, либо отключаются (если они уже существуют), либо не создаются (если это новые кубы для нового чанка).
Чтобы сделать код чище, я решил перенести оптимизацию границ и углов куба в отдельные классы, каждый из которых наследуется от сценария MapOptimization. Я начал со сценария BorderOptimization и использовал действие onIsBorderCube для запуска BorderCubeOptimizationSequence. Я подписался на действие onIsBorderCube в методе Start() функции BorderOptimization. Хотя действие вызывается правильно, после завершения каждой допустимой итерации я сталкиваюсь с исключением NullReferenceException.
Исключение возникает сразу после завершения метода ProcessAllCubeDataOfUpcomingChunk. По какой-то причине метод ProcessAllCubeDataOfUpcomingChunk вызывается снова, но на этот раз действие onIsBorderCube имеет значение null, что приводит к сбою.
Сценарий MapOptimization ниже
Скрипт не полный, я удалил другие элементы, чтобы предварительный просмотр был кратким. Если вы что-то пропустите, сообщите мне, и я добавлю это.
Код: Выделить всё
public class MapOptimization : MonoBehaviour
{
protected Action onIsBorderCube;
private void ProcessAllCubeDataOfUpcommingChunk(Dictionary newChunkFieldData, Vector3 centerOfNewChunk)
{
centerOfXNegativeNeighbourChunk = new Vector3(centerOfNewChunk.x - mapGenerator.gridSize.x, centerOfNewChunk.y, centerOfNewChunk.z);
centerOfXPositiveNeighbourChunk = new Vector3(centerOfNewChunk.x + mapGenerator.gridSize.x, centerOfNewChunk.y, centerOfNewChunk.z);
centerOfZNegativeNeighbourChunk = new Vector3(centerOfNewChunk.x, centerOfNewChunk.y, centerOfNewChunk.z - mapGenerator.gridSize.z);
centerOfZPositiveNeighbourChunk = new Vector3(centerOfNewChunk.x, centerOfNewChunk.y, centerOfNewChunk.z + mapGenerator.gridSize.z);
XNegativeCorner = centerOfNewChunk.x - Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) + 1.0f;
XPositiveCorner = centerOfNewChunk.x + Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) - 1.0f;
ZNegativeCorner = centerOfNewChunk.z - Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) + 1.0f;
ZPositiveCorner = centerOfNewChunk.z + Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) - 1.0f;
foreach (KeyValuePair newCubeData in newChunkFieldData)
{
OptimizeDataOfNewChunk(newCubeData.Value, centerOfNewChunk, newChunkFieldData);
}
}
private void OptimizeDataOfNewChunk(CubeData newCubeData, Vector3 centerOfNewChunk, Dictionary newChunkFieldData)
{
Border newChunkBorder = Border.Null;
if (isCubeAtBorder(newCubeData.position, ref newChunkBorder))
{
Corner newCubeCorner = Corner.Null;
if (isNewCubeAtCorner(newCubeData, ref newCubeCorner))
{
CornerCubeOptimizationSequence(newCubeData, centerOfNewChunk, newChunkBorder, newCubeCorner);
}
else
{
onIsBorderCube(newChunkFieldData, newCubeData, newChunkBorder);
}
}
else
{
DeactiavateSurroundedCubeData(newCubeData, newChunkFieldData);
}
}
}
Скрипт не полный, я удалил другие элементы, чтобы сделать его предварительный просмотр кратким. Если вы что-то пропустите, сообщите мне, и я добавлю это.
Код: Выделить всё
public class BorderOptimization : MapOptimization
{
void Start()
{
Debug.Log("onIsBorder is subscribbed");
onIsBorderCube += BorderCubeOptimizationSequence;
}
private void BorderCubeOptimizationSequence(Dictionary newChunkFieldData, CubeData newCubeData, Border newChunkBorder)
{
Border neighbourChunkBorder = Border.Null;
Vector3 neighbourCubePosition = Vector3.zero;
Vector3 neighbourChunkCenter = Vector3.zero;
SetNeighborChunkValues(newChunkBorder, newCubeData.position, ref neighbourChunkBorder, ref neighbourCubePosition, ref neighbourChunkCenter);
if (!DoesNeighborChunkExist(neighbourChunkCenter))
{
return;
}
Dictionary neighbourChunkField = mapGenerator.dictionaryOfCentersWithItsChunkField[neighbourChunkCenter];
// Return if New Cube in New Chunk isn't surrounded with cubes from each sides
if (!IsBorderCubeSurrounded(newChunkFieldData, newCubeData.position, neighbourChunkField, neighbourCubePosition, newChunkBorder))
{
return;
}
newCubeData.isCubeDataSurrounded = true;
// Return if Neighbor Cube in Neighbor Chunk isn't surrounded with cubes from each sides
if (!IsBorderCubeSurrounded(neighbourChunkField, neighbourCubePosition, newChunkFieldData, newCubeData.position, neighbourChunkBorder))
{
return;
}
neighbourChunkField[neighbourCubePosition].cubeInstance.gameObject.SetActive(false);
}
}
Проблема, с которой я столкнулся, заключается не в том, что действие onIsBorderCube вызывает исключение NullReferenceException, а в том, что метод ProcessAllCubeDataOfUpcommingChunk вызывается дополнительный раз, чего не должно быть.
p>
Шаги, которые я предпринял:
- Я вернулся к предыдущей реализации, и в этой версии дополнительные вызов ProcessAllCubeDataOfUpcommingChunk не происходит. Это говорит о том, что проблема может заключаться не в самом действии onIsBorderCube, а в другом месте кода.
- Я рассмотрел все ссылки на < strong>ProcessAllCubeDataOfUpcommingChunk и подтвердил, что его следует вызывать только один раз в соответствующем скрипте.
- Во время отладки я заметил, что когда метод вызывается в этот дополнительный раз, отладчик не возвращается к месту, где был вызван ProcessAllCubeDataOfUpcommingChunk.
- Я также проверил стек вызовов на наличие действительных и недопустимых итераций вызова этого метода. Как ни странно, стеки вызовов выглядят одинаково в обоих случаях, несмотря на то, что один из них приводит к дополнительному вызову.
введите здесь описание изображения
Неверная итерация
введите здесь описание изображения
Я предполагаю, что это может происходить из-за порядка выполнения функций событий, но пытаюсь найти причину.
Здесь я отправляю видео, как это выглядит, когда я занимаюсь устранением проблемы.
Подробнее здесь: https://stackoverflow.com/questions/791 ... ty-c-sharp
Мобильная версия