Я хотел бы найти способ реализации алгоритма решения лабиринта Тремо в среде 3D-игр Unity.У меня есть бот, который может перемещаться по лабиринту, используя raycasts и обнаружение столкновений.
Единственный основной способ, которым я могу заставить это работать, - это жесткий код в каждом возможном сценарии с маркерами, размещенными вокруг соединений в соответствии с алгоритмом.и избегать как таковой.Другой способ, который, как я думал, может быть возможен, заключается в том, что бот может каким-то образом нарисовать путь, чтобы понять, где ему необходимо пересмотреть себя.В идеале, если бы я мог получить луч, который был бы использован, где бы ни был бот, я мог бы использовать его для запуска алгоритма.
Показанный код является более ранней версией алгоритма, который использует технику маркировки.
Я уже попробовал и проверил создание экземпляров маркеров, и это отлично работает.Если возможно, меня также интересовали бы любые рекурсивные методы, которые можно было бы использовать.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Tremaux : MonoBehaviour
{
public float speed;
public float distance;
public float frontDistance;
public GameObject SingleMark;
public GameObject DoubleMark;
bool Front = false;
bool FrontWarn = false;
bool Back = false;
bool Left = false;
bool Right = false;
bool Rand;
bool Rand2;
bool MazeExit = false;
bool LeftDetect;
bool RightDetect;
public float frontDistance2;
void Start()
{
}
void Update()
{
if (MazeExit == false)
{
Rand = (Random.value > 0.5f);
Rand2 = (Random.value > 0.5f);
}
RaycastHit Hit;
Ray FrontRay = new Ray(transform.position, transform.forward);
Ray FrontWarnRay = new Ray(transform.position, transform.forward);
Ray BackRay = new Ray(transform.position, -transform.forward);
Ray LeftRay = new Ray(transform.position, -transform.right);
Ray RightRay = new Ray(transform.position, transform.right);
Ray RightDetectRay = new Ray(transform.position, transform.right);
Ray LeftDetectRay = new Ray(transform.position, -transform.right);
Debug.DrawRay(transform.position, transform.forward * frontDistance2);
Debug.DrawRay(transform.position, transform.forward * frontDistance);
Debug.DrawRay(transform.position, -transform.forward * frontDistance);
Debug.DrawRay(transform.position, -transform.right * frontDistance);
Debug.DrawRay(transform.position, transform.right * frontDistance);
//transform.Rotate(0, 90, 0);
Front = false;
FrontWarn = false;
Back = false;
Left = false;
Right = false;
LeftDetect = false;
RightDetect = false;
if (Physics.Raycast(RightDetectRay, out Hit, frontDistance))
{
if (Hit.collider.tag == "SingleMark")
{
RightDetect = true;
}
}
if (Physics.Raycast(LeftDetectRay, out Hit, frontDistance))
{
if (Hit.collider.tag == "SingleMark")
{
LeftDetect = true;
}
}
if (Physics.Raycast(FrontRay, out Hit, frontDistance2))
{
if (Hit.collider.tag == "wall")
{
Front = true;
}
}
if (Physics.Raycast(FrontWarnRay, out Hit, frontDistance))
{
if (Hit.collider.tag == "wall")
{
FrontWarn = true;
}
}
if (Physics.Raycast(BackRay, out Hit, frontDistance))
{
if (Hit.collider.tag == "wall")
{
Back = true;
}
}
if (Physics.Raycast(RightRay, out Hit, distance))
{
if (Hit.collider.tag == "wall")
{
Right = true;
}
}
if (Physics.Raycast(LeftRay, out Hit, distance))
{
if (Hit.collider.tag == "wall")
{
Left = true;
}
}
if (Right == false && Left == false && Front == true && Back == false) //front is not detected
{
Front = false;
Debug.Log("Junction");
if (Rand == true) //if the random bool is true
{
transform.Rotate(0, 90, 0);
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 2.5f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(2.5f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Right (Junction)");
}
if (Rand == false)
{
transform.Rotate(0, -90, 0);
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 2.5f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(-2.5f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Left (Junction)");
}
Rand = false;
}
if (Right == false && Left == false && FrontWarn == false && Back == false) //front is not detected
{
Front = false;
Debug.Log("Crossroads");
transform.Translate(0, 0, 1.25f);
if (RightDetect == true && LeftDetect == true)
{
Debug.Log("SingleMarks detected left & right! (Crossroads)");
RightDetect = false;
LeftDetect = false;
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, -4));
Instantiate(DoubleMark, spawnPoint1, Quaternion.identity);
transform.Rotate(0, 180, 0);
transform.Translate(0, 0, 1.25f);
}
if (RightDetect == false && LeftDetect == false)
{
if (Rand == true) //if the random bool is true
{
if (Rand2 == true)
{
transform.Rotate(0, 90, 0);
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 2.25f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(2.25f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Right (crossroads)");
}
if (Rand2 == false)
{
Debug.Log("Straight Ahead at Crossroads!");
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 4));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(0, 0, -1.5f));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
transform.Translate(0, 0, 1.75f);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
}
}
if (Rand == false)
{
transform.Rotate(0, -90, 0);
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 2.25f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(-2.25f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Left (crossroads)");
}
}
Rand = false;
Rand2 = false;
}
transform.Translate(Vector3.forward * Time.deltaTime * speed);
if (Front == true)
{
Front = false;
if (Left == true && Right == false)
{
Left = false;
Debug.Log("right");
transform.Rotate(0, 90, 0);
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 2.25f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(2.25f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
}
if (Right == true && Left == false)
{
Left = false;
Debug.Log("left");
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, -2.25f));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(-2.25f, 0, 0));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
transform.Rotate(0, -90, 0);
}
if (Right == true && Left == true)
{
Left = false;
Debug.Log("back");
transform.Rotate(0, 180, 0);
}
}
//Debug.Log(Rand);
if (Left == true && Right == false && FrontWarn == false && Back == false)
{
Left = false;
if (FrontWarn == false)
{
if (Rand == true) //if the random bool is true
{
transform.Translate(0, 0, 1.25f);
transform.Rotate(0, 90, 0);
//transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Right: " + Rand);
}
if (Rand == false)
{
Vector3 spawnPoint1 = transform.position + (transform.rotation * new Vector3(0, 0, 4));
Vector3 spawnPoint2 = transform.position + (transform.rotation * new Vector3(0, 0, -1.5f));
Instantiate(SingleMark, spawnPoint1, Quaternion.identity);
transform.Translate(0, 0, 3);
Instantiate(SingleMark, spawnPoint2, Quaternion.identity);
Debug.Log("Straight Ahead!");
}
Rand = false;
}
}
if (Right == true && Left == false && FrontWarn == false && Back == false)
{
Right = false;
if (FrontWarn == false)
{
if (Rand == true) //if the random bool is true
{
transform.Translate(0, 0, 1.25f);
transform.Rotate(0, -90, 0);
//transform.Translate(0, 0, 1.25f);
Debug.Log("Turned Right: " + Rand);
}
if (Rand == false)
{
transform.Translate(0, 0, 3);
Debug.Log("Straight Ahead!");
}
Rand = false;
}
}
}
}
Так что, в принципе, я был бы признателен за метод, позволяющий нарисовать путь, по которому бот может пересмотреть при необходимости, или за любые другие идеи о том, как лучше справиться с этим.
Спасибо завперед.