Search Unity

Check if Two Rooms are Connected

Discussion in 'Scripting' started by RobertOne, Jun 5, 2015.

  1. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    Hey!
    Iam currently working on a Game where you got a Maze and you have rotate the Maze Parts in a certain Time period. The Maze will get generated by hand by me. the whole thing looks like that:

    what i want to do now is that my game checks that the start and finish point are connected/the puzzle got solved and my simple question would be: how can i do this?

    so there are more than one way to solve the puzzle as you can see since there are different paths so i can not do something like "if this peace1 got rotated two times and this peace2 got rotated three times and peace3 one time = puzzle solved"

    is there a way to maybe sent in invisible laser every frame from the start point to the finish point and see if will gets threw the finish point or something like that?
     
  2. MarioRuiz

    MarioRuiz

    Joined:
    Nov 7, 2009
    Posts:
    161
    There's a number of ways to approach it, the one that involves less coding that I could think of is making use of unity's pathfinding, bake a plane with zero obstacles on your floor as the navmesh and the walls on your objects should be navmesh obtacles, that way you can after every move check if there's a valid path from start to finish. this would not be an overkill or particularly heavy use of pathfinding.

    Other way could be creating an object on the start position that checks for obstacles in the four directions fw bw left and right (raycast) and if it does not find obstacles (walls) on a direction creates a new one on the empty spot it just found and so on and so on, if there's a path eventually the raycast would hit your finish object (they would need to be pooled to avoid unnecesary instantiation and destroy calls) Hope it was clear.
     
    Korno and RobertOne like this.
  3. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    cool, thanks for the inspiration. i think the navmesh solution sounds pretty good to me :)
     
  4. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    okay, i have to ask again, how can i set this up correctly?
    my maze part looks like this for example:


    so i put a navmesh obstacle on it but how can i leave the dark-blue area still walkable? only the light blue parts should be the obstacles, right?
     
  5. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    You are going to need multiple obstacles on it. Not sure if a game object can have more than one but what you could do is make empty game objects children and add the obstacles to them.
     
    RobertOne likes this.
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Attach a bunch of rectangle shaped navmesh obstacles as child objects until you have covered everything. For the part from the picture, you'll need three.

    @Korno beat me to it!
     
    RobertOne likes this.
  7. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    @Baste Great minds think alike!
     
    RobertOne likes this.
  8. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    Thanks, that was easy. First i tried to add 3 navmeshobstacle in one gameobject but that didnt worked. But having 3 child objects in it works perfekt. Thanks guys :)
     
  9. MarioRuiz

    MarioRuiz

    Joined:
    Nov 7, 2009
    Posts:
    161
    yep, you're on the right track
     
  10. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    okay, i have to bump this thread up again cause iam stucked a little bit. so what i did so far:
    set everything up like Mario was recommending it. looks like this now:



    and works pretty fine. i can now sent the player to every position in the maze by clicking on the right spot using this script:
    Code (CSharp):
    1. using UnityEngine;
    2. public class NavMesh : MonoBehaviour {
    3.      NavMeshAgent agent;
    4.    
    5.      void Start() {
    6.          agent = GetComponent<NavMeshAgent>();
    7.      }
    8.    
    9.      void Update() {
    10.          if (Input.GetMouseButtonDown(0)) {
    11.              RaycastHit hit;
    12.            
    13.              if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 100)) {
    14.                  agent.destination = hit.point;
    15.              }
    16.          }
    17.      }
    18. }
    now iam at this part:
    so my goal is (as you can see on the image above) that you have to "un-puzzle" the maze and then the player runs automatically from the startpoint to the finish point as soon as it is possible.

    now my question:
    how can i check now if the start and finish point is connected?
    i know there is something like "NavMeshPathStatus.PathComplete:" but how can I use this for my case?
     
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    The status tells you if a complete paths exists from the starting point to the end point of the agent's path. So if that one's true, then the puzzle should be solved.

    I would use NavMesh.CalculatePath instead of a NavMeshAgent, though, as the agent isn't really something you need to solve your problem.
     
  12. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    Thank you! just red threw the Docs (http://docs.unity3d.com/ScriptReference/NavMesh.CalculatePath.html) and it make sense :)
    somehow i tried the script from the docpage now, just to see if it works:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. public class ShowGoldenPath : MonoBehaviour {
    4.     public Transform target;
    5.     private NavMeshPath path;
    6.     private float elapsed = 0.0f;
    7.     void Start () {
    8.         path = new NavMeshPath();
    9.         elapsed = 0.0f;
    10.     }
    11.     void Update () {
    12.         // Update the way to the goal every second.
    13.         elapsed += Time.deltaTime;
    14.         if (elapsed > 1.0f) {
    15.             elapsed -= 1.0f;
    16.             NavMesh.CalculatePath(transform.position, target.position, NavMesh.AllAreas, path);
    17.         }
    18.         for (int i = 0; i < path.corners.Length-1; i++)
    19.             Debug.DrawLine(path.corners[i], path.corners[i+1], Color.red);      
    20.     }
    21. }
    22.  
    but on line 16 it keeps telling me:
    NavMesh does contain a definition for "CalculatePath"
    and
    NavMesh does contain a definition for "AllAreas"
     
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    On the script you posted above, you've named your class NavMesh. The C# compiler starts looking for names in the local folders, before it starts looking in the imports ("using ..."). So it's looking for the CalculatePath method in your NavMesh class, where there is no such method. Just rename your class, and you'll be fine. Of if you really insist on naming it "NavMesh", use UnityEngine.NavMesh when you need to reference the one from the UnityEngine namespace.

    In general, don't name your classes the same as classes from the Unity official stuff.
     
    RobertOne likes this.
  14. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
    Ah, always learning something new :)
    Thats why it worked in a new blank project :)
     
  15. RobertOne

    RobertOne

    Joined:
    Feb 5, 2014
    Posts:
    259
  16. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Yeah, you'll get true out if the path is just partial. I complained about it on the documentation forums, and it's apparently going to show up in the docs. Because of this, you can't use if(NavMesh.CalculatePath(...)) to figure out if there's a path from your start to your exit.

    The biggest difference between the two is that NavMesh.CalculatePath is static, so you don't need an object to call it. NavMeshAgent.CalculatePath requires you to have a NavMeshAgent in the scene (which you don't really need).

    NavMeshAgent takes information about the agent into account (I believe) - so if the agent has a radius that's larger than the width of a corridor, it won't move through that corridor. I also think it gives points that are offset from corners by the agent's radius, but I might be mistaken. It also uses the walkable mask of the NavMeshAgent, while you have to supply your own if you need it for NavMesh.CalculatePath. You don't need that, though, so don't worry about that.
     
    RobertOne likes this.
  17. MarioRuiz

    MarioRuiz

    Joined:
    Nov 7, 2009
    Posts:
    161
    @Baste interesting,I'm using NavMesh.CalculatePath and it always gives me false when the path is interrupted/not possible... will look into that to test it a little.

    @RobertOne so you're testing from player to exit not from start to exit, ok, didn't know you had a player in there... Are you going to show the path to help the player?
     
    Last edited: Jun 9, 2015