#c# #unity3d
#c# #unity-игровой движок
Вопрос:
Я пытаюсь создать игру-головоломку, в которой игроку представлена сетка труб с одним источником воды. Игрок должен вращать трубы, чтобы соединить их все друг с другом и, конечно, с источником воды.
Проблема, с которой я застрял, заключается в следующем:
Шаг 1:
Шаг 2:
Шаг 3:
Как показано на рисунках, когда я поворачиваю трубу, которая подключена к группе других труб, соединение с водой не прерывается в оставшейся группе, оно работает только в одной смежной трубе.
Это происходит из-за того, как я выполняю соединения, используя группу коллайдеров на каждом выходе из труб, как показано на рисунках ниже.
Коллайдеры — Сцена:
Коллайдеры — иерархия:
Если столкнувшийся объект подключен к water (с помощью bool), он добавляет столкнувшийся объект в список. Если список больше 0, активируется синий спрайт. Если список пуст, деактивирует синий спрайт. Как показано в примере кода ниже.
Триггеры, которые проверяют, подключен ли объект к воде:
private void OnTriggerEnter2D(Collider2D other) {
if (other.GetComponent<FlipPipes2>() != null) {
isFlowingWater = other.GetComponent<FlipPipes2>().flowingWater;
}
if (other.CompareTag("WaterPipe")) {
if (other.name == "Filled_Cross" || isFlowingWater) {
myFlipPipes.flowingWater = true;
}
TestingScoreStatic.connectedPipes ;
}
}
private void OnTriggerStay2D(Collider2D other) {
if (!inList) {
myFlipPipes.collidedObjectsList.Add(other.gameObject);
inList = true;
}
if (other.name == "Filled_Cross" || isFlowingWater) {
myFlipPipes.flowingWater = true;
}
}
private void OnTriggerExit2D(Collider2D other) {
if (other.CompareTag("WaterPipe")) {
myFlipPipes.collidedObjectsList.Remove(other.gameObject);
myFlipPipes.flowingWater = false;
isConnectedToWater = false;
TestingScoreStatic.connectedPipes--;
inList = false;
}
}
Пример кода фактического изменения спрайта:
private void Update() {
if (collidedObjectsList.Count > 0) {
filledPipe.SetActive(true);
} else {
filledPipe.SetActive(false);
}
}
Даже если плитка, подключенная к источнику воды, теряет свою связь, другие этого не делают, потому что они все еще подключены к плиткам с водой.
Как я могу проверить, существует ли допустимый путь к источнику воды? Или любой другой способ сделать то, что мне нужно?
Вот несколько других примеров кода, которые могут помочь:
Метод, который создает плату:
private void SetUp() {
for (int i = 0; i < width; i ) {
for (int j = 0; j < height; j ) {
Vector2 tempPosition = new Vector2(i, j);
int tempIndex = levelManager.levelOne[pipeIndex];
GameObject pipe = Instantiate(pipes[tempIndex], tempPosition, Quaternion.identity);
pipe.transform.parent = transform;
allPipes[i, j] = pipe;
if (!pipe.CompareTag("WaterPipe")) {
shuffleSpawnedPipes.pipes.Add(pipe);
}
pipeIndex ;
}
}
shuffleSpawnedPipes.ShufflePipes();
}
(Ужасно) Попытка проверить каждую трубу с помощью двойного for
цикла:
void IsConnectedToWater() {
if (column > 0 amp;amp; column < board.width - 1) {
GameObject leftPipe1 = board.allPipes[column - 1, row];
GameObject rightPipe1 = board.allPipes[column 1, row];
if (leftPipe1.tag == this.gameObject.tag amp;amp; rightPipe1.tag == this.gameObject.tag) {
leftPipe1.GetComponent<Pipe>().connectedToWater = true;
rightPipe1.GetComponent<Pipe>().connectedToWater = true;
connectedToWater = true;
}
}
}
Конечно, это не работает, потому что не проверяется, сталкивается ли текущий объект. Даже при проверке на коллизию результат тот же. Я нахожусь в цикле выполнения множества разных попыток, приводящих к одному и тому же результату.
Комментарии:
1. «Возможно ли что-нибудь?» Это не полезный вопрос, на него можно было бы ответить простым «да», абсолютно обоснованным, но бесполезным. Рассмотрите возможность добавления некоторого кода с реальной попыткой решения проблемы и конкретной проблемы.
2. Спасибо @bradbury9, я улучшу сообщение и перефразирую вопрос.
3. Проблема, которую я вижу здесь, заключается в том, что вы проверяете только объект, который вращается, и тот, который подключен к нему. Но другие трубы, которые были подключены, но больше не являются без поворота, не обновляются. Я бы лично разделил данные о протекании воды и столкновении. Следовательно, у вас может быть алгоритм, который проверяет, какой объект подключен к воде, а какой нет, проще, а затем обновляет представления. Также, когда вы поворачиваете объект, у вас происходит несколько столкновений, первое из которых изменяет состояние объекта, что может быть проблемой для другой подключенной трубы.
Ответ №1:
Что вам нужно, так это алгоритм поиска пути.
Создайте рекурсивную функцию, которая будет проверять пути к вашему источнику воды. Вместо проверки каждого элемента, подключен ли он к water, проверьте, есть ли ваш объект watersource в списке подключенных объектов этого проверяемого канала. Если это не так, сохраните этот объект pipe в списке checkedObjects
и перейдите к следующему подключенному объекту, повторяйте, пока не проверите все объекты pipe, подключенные друг к другу. Если ни у одного из объектов не было вашего источника воды в списке подключенных объектов, это означает, что все объекты на checkedObjects
пути не подключены к воде, и вы можете отключить спрайт воды на всех из них.