Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by tayloreichhorst · Dec 09, 2014 at 12:44 AM · 3dpath

Generating a Random Linear Pathway

I am stuck on this and can't quite wrap my head around what is wrong. I am trying to create a single pathway with random turns, simply starting at 0,0,0 and randomly branching out from there until it hits it's limit. The path also can't intersect itself at any time.

Right now, the code works great unless it's a large path, Unity gets hung up making it. I can't quite figure out where it's getting hung up, I can't get anything print in the console because Unity just freezes. My guess is that it closes in on itself and has nowhere to go, but isn't destroying the path and trying again, which is what I'm trying to get it to do if that happens.

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class PathCreator : MonoBehaviour
 {
         // to do:
         // create path
         // start coroutine
         // create first block
         // create loop for creating other blocks
         // pick random directon
         // after direction selected, find the coordinates of where new step would be
         // check that there isn't already a block there
         // if there isn't, check all coordinates around it.
         // if there are 3 empty coordinates create block
 
 
         public List<Vector2> steps = new List<Vector2> ();
         public List<Vector2> randomDirections = new List<Vector2> ();
         public int pathCountMin;
         public int pathCountMax;
         int pathCount;
         GameObject pathContainer;
         public Material matHidden;
         public Material matShown;
         public Material matCheckPoint;
         public Material matEnd;
 
         // Use this for initialization
         void Start ()
         {
                 //add 4 random directions to the list
                 randomDirections.Add (new Vector2 (0, 1));
                 randomDirections.Add (new Vector2 (0, -1));
                 randomDirections.Add (new Vector2 (1, 0));
                 randomDirections.Add (new Vector2 (-1, 0));
                 
                 pathContainer = GameObject.FindWithTag ("PathContainer");
         }
     
         // Update is called once per frame
         void Update ()
         {
         
         }
 
         public void CreatePath ()
         {
                 steps.Clear ();
 
                 //get a final count to know how long to make the path
                 pathCount = Random.Range (pathCountMin, pathCountMax);
 
                 //create first step to start the path
                 GameObject firstStep = GameObject.CreatePrimitive (PrimitiveType.Cube);
                 firstStep.transform.position = new Vector3 (0, -0.5f, 0);
                 firstStep.transform.localScale = new Vector3 (1, 0.5f, 1);
                 firstStep.name = "Cube " + steps.Count;
                 firstStep.transform.parent = pathContainer.transform;
                 steps.Add (new Vector2 (firstStep.transform.position.x, firstStep.transform.position.z));
 
                 StartCoroutine (CreateSteps ());
 
                 //HidePath ();
 
                 //ShowFirstStep ();                
         }
 
         IEnumerator CreateSteps ()
         {
                 //this will run the code for each step until pathCount is reached
                 for (int i = 0; i <= pathCount - 1; i++) {
                 
                         bool testGood = false;
                         bool blockCreated = false;    
                         List<Vector2> usedDirections = new List<Vector2> ();    
             
                         do {
                                 //find coordinates of the new step and mark openSpace as true if there is no step already there
                                 
                                 Vector2 direction = randomDirections [Random.Range (0, randomDirections.Count)];
                                 Vector2 lastStep = steps [steps.Count - 1];
                                 Vector2 newStep = lastStep + direction;    
 
                                 if (!usedDirections.Contains (direction)) {    
                                         usedDirections.Add (direction);
                                 }
                 
                                 while (steps.Contains(newStep)) {
                                         //destroys path if all directions have been attempted                    
                                         if (usedDirections.Count > 3) {
                                                 DestroyPath ();
                                         } else {
                                                 //picks a new direction until it lands on one that hasn't been used yet.
                                                 while (usedDirections.Contains(direction)) {                    
                                                         direction = randomDirections [Random.Range (0, randomDirections.Count)];
                                                         
                                                 }                            
                                                 if (!usedDirections.Contains (direction)) {                        
                                                         usedDirections.Add (direction);
                                                 }
                                                 newStep = lastStep + direction;
                                         }
                                 }
 
                                 print (usedDirections.Count);
                                 
 
                                 testGood = false;
                                 int testCount = 0;        
 //                                //Check each direction around the new step.  For each empty spot add 1 to testCount.  If 3 
 //                                //successful testCounts exist, mark it as tested.
                                 foreach (Vector2 dir in randomDirections) {
                                         Vector2 testStep = dir + newStep;
                                         if (!steps.Contains (testStep)) {
                                                 testCount += 1;
                                         }
                                 }
 
                                 if (testCount <= 2) {
                                         print ("tests failed");
 
                                         if (!usedDirections.Contains (direction)) {    
                                                 usedDirections.Add (direction);
                                         }
 
                                         testGood = false;
                                 } else if (testCount == 0) { 
                                         DestroyPath ();
                                 } else {
                                         testGood = true;
                                 }
 
                                 
                                 
                                 //if tests pan out, create the next step and move on
                                 if (testGood == true) {
                                         GameObject step = GameObject.CreatePrimitive (PrimitiveType.Cube);
                                         step.transform.position = new Vector3 (newStep.x, -0.5f, newStep.y);
                                         step.transform.localScale = new Vector3 (1, 0.5f, 1);
                                         step.name = "Cube " + steps.Count;
                                         step.transform.parent = pathContainer.transform;
                                         steps.Add (new Vector2 (step.transform.position.x, step.transform.position.z));
 
                                         blockCreated = true;
                                         usedDirections.Clear ();
                                 }                                                        
 
                         } while (blockCreated == false);
                 }
 
                 yield return null;
 
         }
 
         void DestroyPath ()
         {
 
                 StopAllCoroutines ();
 
                 foreach (Transform step in pathContainer.GetComponentsInChildren<Transform>()) {
                         if (step.tag == "PathContainer") {
                 
                         } else {
                                 Destroy (step.gameObject);
                         }
                 }
 
                 steps.Clear ();
 
                 print ("Had to Destroy Path");
 
                 CreatePath ();
 
                 
         }
 
         void HidePath ()
         {
                 foreach (Transform step in pathContainer.GetComponentsInChildren<Transform>()) {
 
                         if (step.tag == "PathContainer") {
 
                         } else {
                                 step.gameObject.renderer.material = matHidden;
                         }
 
                 }
 
 
 
 
         }
 
         void ShowFirstStep ()
         {
 
                 Collider[] colliders;
                 if ((colliders = Physics.OverlapSphere (new Vector3 (0, -0.5f, 0), 0.2f)).Length > 0) { //Presuming the object you are testing also has a collider 0 otherwise
                         foreach (Collider col in colliders) {
                                 GameObject go = col.gameObject;
                                 Debug.Log ("hello");
                                 Debug.Log (go);
 
                                 go.renderer.material = matShown;
 
                         }
                 }
 
 
         }
 
 }
 
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Dec 09, 2014 at 01:18 AM

Well you're doing some really risky stuff here. Your main problem is your DestroyPath calls doesn't do what you expect them to do. You call StopAllCoroutines but that only marks all currently running coroutines to stop at the next yield. Since the DestroyPath call is called from the current coroutine it will continue to execute until the next yield.

For large paths it's very likely that you go into a dead end (every closed spiral will end there). If your algorithm reaches a dead end you just call DestroyPath and don't care about the current iteration. blockCreated will never be true since your usedDirections will contain all 4 directions and your stuck inside that while loop without ever reaching the next yield.

Furthermore each time you call DestroyPath you create a new coroutine which will run up until the first yield and then return from the StartCoroutine call and continue with the very first coroutine which is stuck inside the while loop and just spawns more coroutines without ever actually yield.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image tayloreichhorst · Dec 09, 2014 at 01:21 AM 0
Share

Thanks for the quick reply. All of that makes a lot of sense to me, thanks. I have found some maze tutorials that more or less have the same ideas I am looking for. I think I'll try some new ways and keep what you said in $$anonymous$$d. Thanks!

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

3 People are following this question.

avatar image avatar image avatar image

Related Questions

how to set an object on a path,how to set an object on a track 0 Answers

Trouble again with 3D ellipse {FIXED} 1 Answer

Using the right terminology 1 Answer

How to find % along path between N points 2 Answers

Is there any full 3D-Pathfinding asset/solution? 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges