Как внедрить Tremaux в Unity 3D - PullRequest
0 голосов
/ 07 февраля 2019

Я хотел бы найти способ реализации алгоритма решения лабиринта Тремо в среде 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;
            }
        }
    }
}

Так что, в принципе, я был бы признателен за метод, позволяющий нарисовать путь, по которому бот может пересмотреть при необходимости, или за любые другие идеи о том, как лучше справиться с этим.

Спасибо завперед.

...