Уменьшите избыточный код для оптимизации граничных кубов в проекте Unity C#C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Уменьшите избыточный код для оптимизации граничных кубов в проекте Unity C#

Сообщение Anonymous »

Я только что создал свою учетную запись на StackOverflow и впервые задаю здесь вопрос, поэтому прошу прощения, если пишу что-то неэффективно. Я постараюсь описать свою проблему как можно более подробно, однако, если вам не хватает какой-либо дополнительной информации, сообщите об этом, и я предоставлю ее.
Я выпускаю сценарий оптимизации для моего учебного проекта, в котором я работаю. пытаюсь создать базовую функциональность Minecraft.
Я создал два метода для граничных кубов в кусках, которые гарантируют, что граничные кубы, покрытые с каждого направления другими кубами, не будут создавать экземпляры или, если они уже созданы, они будут деактивированы.
  • ❓ Проблема в том, что эти два метода < strong>содержат избыточный код, от которого я хочу избавиться, чтобы сделать этот скрипт чище.
Следующий метод гарантирует, что если Новый куб в Новом блоке окружен с каждой стороны, он принимает определенный параметр, который не позволит этому кубу создавать экземпляры в будущем.
private void BorderCubesOptimizationsOfNewChunk(CubeData newCubeData, Dictionary newChunkFieldData, Vector3 centerOfNeigbourChunk, Vector3 neighbourCubePosition, Border border, Corner corner)
{
Dictionary neighbourChunk = mapGenerator.dictionaryOfCentersWithItsChunkField[centerOfNeigbourChunk];

// WIP
if (corner != Corner.Null)
{
if (corner == Corner.XNegative_ZNegative)
{

}
else if (corner == Corner.XNegative_ZPositive)
{

}
else if (corner == Corner.XPositive_ZNegative)
{

}
else if (corner == Corner.XPositive_ZPositive)
{

}
return;
}

// If there is a Cube in New Chunk bellow New Cube, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position - Vector3.up))
{
return;
}
// If there is a Cube in New Chunk above New Cube, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position + Vector3.up))
{
return;
}

if (border != Border.XNegative)
{
// If there is a Cube in New Chunk at decremented X position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position - Vector3.right))
{
return;
}
}
else
{
// If there is a Cube in Neighbour Chunk at decremented X position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition))
{
return;
}
}
if (border != Border.XPositive)
{
// If there is a Cube in New Chunk at incremented X position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position + Vector3.right))
{
return;
}
}
else
{
// If there is a Cube in Neighbour Chunk at incremented X position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition))
{
return;
}
}
if (border != Border.ZNegative)
{
// If there is a Cube in New Chunk at decremented Z position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position - Vector3.forward))
{
return;
}
}
else
{
// If there is a Cube in Neighbour Chunk at decremented Z position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition))
{
return;
}
}
if (border != Border.ZPositive)
{
// If there is a Cube in New Chunk at incremented Z position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position + Vector3.forward))
{
return;
}
}
else
{
// If there is a Cube in Neighbout Chunk at incremented Z position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition))
{
return;
}
}

newCubeData.isCubeDataSurrounded = true;
}

Тогда у меня есть очень похожий метод, который гарантирует, что если Соседний куб в Соседний блок окружен с каждой стороны, то он деактивируется. этот куб. Но это не единственное отличие: чтобы все заработало, мне пришлось поменять местами операторы для граничных условий.
private void BorderCubesOptimizationsOfNeighbourChunk(Dictionary newChunkFieldData, CubeData newCubeData, Vector3 centerOfNeigbourChunk, Vector3 neighbourCubePosition, Border border, Corner corner)
{
Dictionary neighbourChunk = mapGenerator.dictionaryOfCentersWithItsChunkField[centerOfNeigbourChunk];

// WIP
if (corner != Corner.Null)
{
if (true)
{

}
else if (true)
{

}
else if (true)
{

}
else if (true)
{

}
return;
}

// If there is a Cube in Neighbour Chunk bellow Neighbour Cube, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition - Vector3.up))
{
return;
}
// If there is a Cube in Neighbour Chunk bellow Neighbour Cube, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition + Vector3.up))
{
return;
}

if (border != Border.XNegative)
{
// If there is Cube in Neighbour Chunk at incremented X position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition + Vector3.right))
{
return;
}
}
else
{
// If there is Cube in New Chunk at incremented X position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position))
{
return;
}
}
if (border != Border.XPositive)
{
// If there is Cube in Neighbour Chunk at decremented X position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition - Vector3.right))
{
return;
}
}
else
{
// If there is Cube in New Chunk at decremented X position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position))
{
return;
}
}
if (border != Border.ZNegative)
{
// If there is Cube in Neighbour Chunk at incremented Z position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition + Vector3.forward))
{
return;
}
}
else
{
// If there is Cube in New Chunk at incremented Z position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position))
{
return;
}
}
if (border != Border.ZPositive)
{
// If there is cube in Neighbour Chunk at decremented Z position, then return
if (!neighbourChunk.ContainsKey(neighbourCubePosition - Vector3.forward))
{
return;
}
}
else
{
// If there is cube in New Chunk at decremented Z position, then return
if (!newChunkFieldData.ContainsKey(newCubeData.position))
{
return;
}
}

neighbourChunk[neighbourCubePosition].cubeInstance.gameObject.SetActive(false);

И здесь я скорее предоставляю метод, использующий оба метода, которые я предоставил выше. Этот метод тоже можно оптимизировать, чтобы избавиться от лишнего кода, но я буду работать над этим в будущем.
private void OptimizeDataOfNewChunk(CubeData newCubeData, Vector3 centerOfUpcomingChunk, Dictionary newChunkFieldData)
{
Border border = Border.Null;
Corner corner = Corner.Null;

// Negative X border of actual chunk
// If actual cube postion is on border of actual chunk and if border chunk exist, optimalize borders of these two chunks
if ((newCubeData.position.x - (mapGenerator.gridSize.x / 2)) % mapGenerator.gridSize.x == 0)
{
if (mapGenerator.dictionaryOfCentersWithItsChunkField.ContainsKey(centerOfXPositiveNeighbourChunk))
{
border = Border.XPositive;
// WIP: X positive - Z positive corner
if (newCubeData.position.z == centerOfUpcomingChunk.z + Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) - 1.0f)
{

}

// WIP: X positive - Z negative corner
else if (newCubeData.position.z == centerOfUpcomingChunk.z - Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) + 1.0f)
{

}

BorderCubesOptimizationsOfNewChunk(newCubeData, newChunkFieldData, centerOfXPositiveNeighbourChunk, newCubeData.position + Vector3.right, border, Corner.Null);
BorderCubesOptimizationsOfNeighbourChunk(newChunkFieldData, newCubeData, centerOfXPositiveNeighbourChunk, newCubeData.position + Vector3.right, border, Corner.Null);
return;
}
}
// Positive X border of actual chunk
// If actual cube postion is on border of actual chunk and if border chunk exist, optimalize borders of these two chunks
else if ((newCubeData.position.x + (mapGenerator.gridSize.x / 2)) % mapGenerator.gridSize.x == 0)
{
if (mapGenerator.dictionaryOfCentersWithItsChunkField.ContainsKey(centerOfXNegativeNeighbourChunk))
{
border = Border.XNegative;
// WIP: X negative - Z positive corner
if (newCubeData.position.z == centerOfUpcomingChunk.z + Mathf.Ceil((float)mapGenerator.gridSize.z / 2.0f) - 1.0f)
{

}

// WIP: X negative - Z negative corner
else if (newCubeData.position.z == centerOfUpcomingChunk.z - Mathf.Ceil((float)mapGenerator.gridSize.z / 2.0f) + 1.0f)
{

}

BorderCubesOptimizationsOfNewChunk(newCubeData, newChunkFieldData, centerOfXNegativeNeighbourChunk, newCubeData.position + Vector3.left, border, Corner.Null);
BorderCubesOptimizationsOfNeighbourChunk(newChunkFieldData, newCubeData, centerOfXNegativeNeighbourChunk, newCubeData.position + Vector3.left, border, Corner.Null);
return;
}
}
// Negative Z border of actual chunk
// If actual cube postion is on border of actual chunk and if border chunk exist, optimalize borders of these two chunks
else if ((newCubeData.position.z - (mapGenerator.gridSize.x / 2)) % mapGenerator.gridSize.x == 0)
{
if (mapGenerator.dictionaryOfCentersWithItsChunkField.ContainsKey(centerOfZPositiveNeighbourChunk))
{
border = Border.ZPositive;
// Z positive - X positive corner
if (newCubeData.position.x == centerOfUpcomingChunk.x + Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) - 1.0f)
{

}

// Z negative - X negative corner
else if (newCubeData.position.x == centerOfUpcomingChunk.x - Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) + 1.0f)
{

}

BorderCubesOptimizationsOfNewChunk(newCubeData, newChunkFieldData, centerOfZPositiveNeighbourChunk, newCubeData.position + Vector3.forward, border, Corner.Null);
BorderCubesOptimizationsOfNeighbourChunk(newChunkFieldData, newCubeData, centerOfZPositiveNeighbourChunk, newCubeData.position + Vector3.forward, border, Corner.Null);
return;
}
}
// Postive Z border of actual chunk
// If actual cube postion is on border of actual chunk and if border chunk exist, optimalize borders of these two chunks
else if ((newCubeData.position.z + (mapGenerator.gridSize.x / 2)) % mapGenerator.gridSize.x == 0)
{
if (mapGenerator.dictionaryOfCentersWithItsChunkField.ContainsKey(centerOfZNegativeNeighbourChunk))
{
border = Border.ZNegative;
// Z negative - X positive corner
if (newCubeData.position.x == centerOfUpcomingChunk.x + Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) - 1.0f)
{

}

// Z negative - X negative corner
else if (newCubeData.position.x == centerOfUpcomingChunk.x - Mathf.Ceil((float)mapGenerator.gridSize.x / 2.0f) + 1.0f)
{

}

BorderCubesOptimizationsOfNewChunk(newCubeData, newChunkFieldData, centerOfZNegativeNeighbourChunk, newCubeData.position + Vector3.back, border, Corner.Null);
BorderCubesOptimizationsOfNeighbourChunk(newChunkFieldData, newCubeData, centerOfZNegativeNeighbourChunk, newCubeData.position + Vector3.back, border, Corner.Null);
return;
}
}

DeactiavateSurroundedCubeData(newCubeData, newChunkFieldData);
}

Я думаю, что можно поместить все условия из методов BorderCubesOptimizationsOfNewChunk и BorderCubesOptimizationsOfNeighbourChunk в один метод, используя универсальные шаблоны.
Я знаю, что такое дженерики, и спокойно знаю, как использовать их на очень низком уровне, но раньше я не использовал их в более сложном коде. Я пытался найти документацию и видео, чтобы научиться использовать дженерики, но это не помогло мне даже убедиться, что я на правильном пути.
Также я попросил ChatGPT разделить эти два метода на один, используя дженерики, и ни один из его ответов ни на шаг не приблизил меня к решению этой головоломки. Я попробовал одну реализацию, которую она мне предоставила, но она дала мне внеочередной ответ, который делает дженерики метода OptimizeDataOfNewChunk, но я даже не использовал ее.
Однако, даже если я попытаюсь использовать дженерики для обобщения словарей, которые я использую как фрагменты, я не знаю, как обеспечить это для Соседних кубов или Новых кубов , будут оцененные операторы с соответствующими условиями.
Буду очень благодарен за советы по дизайну или ссылки на обучение материал, который предоставит мне эффективный способ решить эту проблему. 🙏
Тема решена. Мой новый код выглядит так.
private void BorderCubeOptimizationSequence(Dictionary newChunkFieldData, CubeData newCubeData, Border newChunkBorder, Dictionary neighbourChunkField, Vector3 neighbourCubePosition, Border neighbourChynkBorder)
{
// 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, neighbourChynkBorder))
{
return;
}
neighbourChunkField[neighbourCubePosition].cubeInstance.gameObject.SetActive(false);
}

private bool IsBorderCubeSurrounded(Dictionary firstChunkFieldData, Vector3 firstCubePosition, Dictionary secondChunkFieldData, Vector3 secondCubePosition, Border border)
{
foreach (Border actaualBorder in borders)
{
foreach (Vector3 actualDirection in directions)
{
// Continue to the next foreach interation if Actual Direction is the same as Current Border
if (isDirectionSameAsBorder(actualDirection, border))
{
continue;
}

if (actaualBorder != border)
{
if (!firstChunkFieldData.ContainsKey(firstCubePosition + actualDirection))
{
return false;
}
}
else
{
if (!secondChunkFieldData.ContainsKey(secondCubePosition))
{
return false;
}
}
}
}

return true;
}

private bool isDirectionSameAsBorder(Vector3 actualDirection, Border border)
{
if (actualDirection == Vector3.right && border == Border.XPositive)
{
return true;
}
if (actualDirection == -(Vector3.right) && border == Border.XNegative)
{
return true;
}
if (actualDirection == Vector3.forward && border == Border.ZPositive)
{
return true;
}
if (actualDirection == -(Vector3.forward) && border == Border.ZNegative)
{
return true;
}

return false;
}


Подробнее здесь: https://stackoverflow.com/questions/789 ... rp-project
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»