我想找到一种将Tremaux迷宫求解算法实现到Unity 3D游戏环境中的方法。我有一个机器人,可以使用光线投射和碰撞检测在迷宫中导航。
我能使它起作用的唯一主要方法是,在每种可能的情况下,根据算法在结点周围放置标记,并进行硬编码,避免这样做。我认为可能的另一种方式是,如果机器人可以以某种方式画出一条路径来了解它需要在哪里进行自我跟踪。理想情况下,如果我可以将射线投射到机器人所处的任何地方,都可以使用它来运行算法。
显示的代码是使用标记技术的算法的早期版本。
我已经尝试并测试了标记的实例化,并且效果很好。如果可能的话,我也将对可以使用的任何递归技术感兴趣。
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;
}
}
}
}
因此,基本上,我希望能找到一种方法来确定机器人可以在需要时重新跟踪的路径,或者是其他有关如何更好地解决此问题的想法。
谢谢。