• 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 RigbySug · Feb 07, 2020 at 02:49 PM · scripting probleminstantiaterandom.rangealgorithmorder

How to Instatiate with space by order ?

Hello guys, i want instatiate object random on screen but with order.

I'm genearting object random on X and Y axis but i need to make it with my object size. I mean object must be pass way everytime. I hope you will understand that sorry for my english.

Here is my code;

 public Gameobject block1
     
  for (int i = 0; i < 30; i++)
      {
      Vector3 rndVector = new Vector3(Random.Range(-2.55f, 2.55f), Random.Range(-1.6f, 4.1f), 0);
      GameObject block = Instantiate(block1, rndVector, Quaternion.identity);
      float XYZ = Random.Range(0.27f,0.7f);
      block.transform.localScale = new Vector3(XYZ, XYZ, XYZ);
     }

alt text

In Game Looking Like This:

alt text

df.png (17.6 kB)
asd.png (212.2 kB)
Comment
Add comment · Show 2
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 unity_ek98vnTRplGj8Q · Feb 07, 2020 at 04:13 PM 0
Share

I'm having trouble understanding what you want, can you try explaining again please

avatar image phosphoer · Feb 07, 2020 at 06:51 PM 0
Share

are you asking how to prevent the objects from overlapping?

4 Replies

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

Answer by Bunny83 · Feb 08, 2020 at 11:42 AM

Ok I think I finally understood what this question is about. You just want to create 30 circular objects on the screen, randomly distributed, but without any overlap. It seems your other question was about the same issue but your approach was a bit strange. You probably should delete your other question as it's far more confusing what the outcome should be, so it's unlikely anybody will be able to answer it.


To distribute objects on the screen there are several approaches that would work. The most easiest way is to just put every object on its own vertical line and make sure that line is as far away from the previous line as the sum of the previous radius and your current radius. That way no matter where you place your object on that line it can never intersect with the previous one. However this will produce some constraints how the objects are distributed. With this approach it's impossible to have two objects next to each other on about the same line, even though there's enough space to put it there. So this approach will generally produce certain patterns and highly limit the amout of objects we can put on the screen since we essentially stack the objects on top of each other one-dimensionally.


Properly distribute objects randomly is a bit more tricky. In general you have to track / remember / save the position and dimension of all your previous created objects in order to check if there might be an overlap. There are several approaches to do this. I will quickly show some of them:


  • Just rely on Unity's physics system and use colliders and OverlapSphere (when 2d physics is used OverlapCircle). Just pick a random point and radius and see if you get an overlap, if you do generate a new position / radius and try again.

  • Just store all your object data in a list so you can easily access the generated position and radius. Now when generating a new object you can manually iterate through the list and see if the new position / radius wouldl overlap with any of the existing ones. If not we can create an object there and add it to the list. There's a CodingTrain video about this approach

  • The last approach uses a completely different approach. We just generate 30 random objects like you already did. But then we essentially run refinement steps over all objects. We essentially build a simple seperation logic. If we detect two object are overlapping we seperate them by moving them apart by half the overlap amount. This will ensure those two object do not overlap anymore. However by pushing them apart we might move one or both object over other objects or out of the viewing area. This doesn't matter since we do this process several times until there's no overlap anymore.


All these algorithms are not cheap from a performance point of view and all have the possibility of running forever. This happens when you just picked too many objects and you can not possibly fit that many circles into the screen area without overlap. So in all 3 approaches we have to ensure to stop at some point. Otherwise your application would just freeze and has to be force closed.


Physics based approach

So now tackle them one by one. For the first approach it's important to remember that creating objects with a collider in a loop has the issue that those new objects are unknown to the physics system until the next physics step runs. Since everything happens inside a loop the physics system can not detect any of the objects we have already created. Though we can now use Physics2D.SyncTransforms / Physics.SyncTransforms after we created an object to ensure the physics system is up to date. To actually create the object we could use a nested loop or just a variable to track how many tries we had and how many objects we have created already. This can be done with a single for loop:

 float minSpacing = 0f;
 Physics2d.SyncTransforms();
 for (int i=0,c=0; i < 1000 && c < 30; i++)
 {
     Vector3 rndVector = new Vector3(Random.Range(-2.55f, 2.55f), Random.Range(-1.6f, 4.1f), 0);
     float radius = Random.Range(0.27f,0.7f);
     if (Physics2D.OverlapCircle(rndVector, radius + minSpacing) == null)
     {
         GameObject block = Instantiate(block1, rndVector, Quaternion.identity);
         block.transform.localScale = new Vector3(radius, radius, 1f);
         c++;
         Physics2d.SyncTransforms();
     }
 }

So this loop will end when we either have created 30 objects, or when we run that loop 1000 times. So in case there is no room left to fit another circle in we just stop even though we did not create 30 objects. Note that "minSpacing" adds some extra amount to the radius to ensure two circles are not "touching" each other. Just increase this value if you want to have a minimum space between circles.

Even this approach uses Unity's 2d physics system it's probably one of the cheapest solutions because the physics system is highly optimised. However if performance is a concern, do a benchmark and test it.


Simple manual overlap test

Here we just create a List of custom objects which hold the information we need to define a circle object. At each step, like in the last approach, we generate a new position and radius and see if it overlaps with other circles and if it does, create a new one until we don't have an overlap..

 static float minSpacing = 0f;
 public class Circle
 {
     public Vector2 pos;
     public float radius;
     public bool Overlap(Circle aOther)
     {
         float rad = radius + aOther.radius + minSpacing;
         return (aOther.pos - pos).sqrMagnitude < rad*rad;
     }
 }
 
 List<Circle> circles = new List<Circle>();
 
 void Start()
 {
     for (int i=0,c=0; i < 1000 && c < 30; i++)
     {
         Vector3 rndVector = new Vector3(Random.Range(-2.55f, 2.55f), Random.Range(-1.6f, 4.1f), 0);
         float radius = Random.Range(0.27f,0.7f);
         var newCircle = new Circle{ pos = rndVector, radius = radius };
         
         bool validCircle = true;
         foreach(var c in circles)
         {
             if (c.Overlap(newCircle))
             {
                 validCircle = false;
                 break;
             }
         }
         
         if (validCircle)
         {
             GameObject block = Instantiate(block1, rndVector, Quaternion.identity);
             block.transform.localScale = new Vector3(radius, radius, 1f);
             circles.Add(newCircle);
             c++;
         }
     }
 }

So this is the same approach as the first one but without any physics system involvement.


Refinement approach

In this case we create 30 random Circle objects right away. We run several refinement steps which wil gradually seperate the objects. Note that the end result will differ from the other two cases. In the first to approaches if we can't fit enough circles into the area we simply give up adding more circles after some point. So we end up with less circles than we wanted. This approach will always create as many circles as we want. However if there are too many circles they might still overlap after we run out max refinement steps. There's no nice way to solve this issue with this approach.

 static float minSpacing = 0f;
 public class Circle
 {
     public Vector2 pos;
     public float radius;
     public bool Refine(Circle aOther)
     {
         float rad = radius + aOther.radius + minSpacing;
         var dir = aOther.pos - pos;
         float overlap = rad*rad - dir.sqrMagnitude;
         if ( overlap > 0 )
         {
             overlap = Mathf.Sqrt(overlap);
             dir = dir.normalized * overlap * 0.5f;
             pos -= dir;
             aOther.pos += dir;
         }
     }
 }
 
 List<Circle> circles = new List<Circle>();
 
 void Start()
 {
     for (int c = 0; c < 30; c++)
     {
         Vector3 rndVector = new Vector3(Random.Range(-2.55f, 2.55f), Random.Range(-1.6f, 4.1f), 0);
         float radius = Random.Range(0.27f,0.7f);
         var newCircle = new Circle{ pos = rndVector, radius = radius };
         circles.Add(newCircle);
     }
     for(int i = 0; i < 100; i++)
     {
         bool refined = false;
         for (int a = 0; a < circles.Count; a++)
         {
             for (int b = a; b < circles.Count; b++)
             {
                 if(circles[a].Refine(circles[b]))
                     refined = true;
             }
         }
         if (!refined)
             break;
         // ensure points are not pushed outside our initial range
         foreach(var c in circles)
         {
             c.pos.x = Mathf.Clamp(c.pos.x, -2.55f, 2.55f);
             c.pos.y = Mathf.Clamp(c.pos.y, -1.6f, 4.1f);
         }
     }
     foreach(var c in circles)
     {
         GameObject block = Instantiate(block1, c.pos, Quaternion.identity);
         block.transform.localScale = new Vector3(c.radius, c.radius, 1f);
     }
 }


Note that all of this code is untested. I have just written it here from scratch. If you find any error, let me know in a comment.

Comment
Add comment · Show 5 · 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 RigbySug · Feb 08, 2020 at 04:42 PM 0
Share

First thanks for helping about that.

I watched CodeTrain's video and i searched about Possion Dics Sampling i read so many texts etc.

I tested "Physics based approach" code it didn't work i mean here i used code and result ;

https://i.hizliresim.com/NG6JkP.png

https://i.hizliresim.com/agJRXO.png

"Simple manual overlap test" have problem on foreach(var c in circle)

And "Refinement approach" have problem on here public bool Refine(Circle aOther)

I'm trying to make this game but i have so many trouble with that pf.

Game Link ;

avatar image phosphoer RigbySug · Feb 08, 2020 at 11:58 PM 1
Share

For the physics approach, make sure your block1 prefab actually has a 2d collider on it that matches its visual.

The foreach var c in circle is just a typo, it should be 'circles'.

For the refinement problem, the function just isnt' returning a bool yet, it should return false inside the if block and return true at end.

All 3 of those approaches are very reasonable and should work, it sounds like there are just a couple $$anonymous$$or bugs remaining so you are almost there!

avatar image Bunny83 phosphoer · Feb 09, 2020 at 12:39 AM 1
Share

Yep, that was a typo ^^ I just fixed it, thanks. And yes, even though I mentioned "objects with colliders" in the introduction, I never explititly said that the prefab must have one. Though one certain thing should be kind of obvious ^^. I also did not mention that the script need to be attached to a gameobject in the scene. However that's probably more obvious than the need for a 2d collider when using 2d physics :)


Note that I just replaced Physics2D.Simulate(0f) with Physics2D.SyncTransforms() which is more correct and probably less demanding.

Show more comments
avatar image
1

Answer by RigbySug · Feb 07, 2020 at 09:30 PM

Anyone can help on this please. Nobody not know it?

Comment
Add comment · Show 2 · 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 unity_ek98vnTRplGj8Q · Feb 07, 2020 at 10:34 PM 0
Share

Please answer the questions in the comments of your post so we can help you

avatar image RigbySug unity_ek98vnTRplGj8Q · Feb 07, 2020 at 11:10 PM 0
Share

I'm genarting object with instatie as you can see. But here is problem object up on object because Random.Range calling close number like(1.1F, 1.3F, 1.8F) and it's about size. How can i genarate object like picture 1. Thanks.

avatar image
0

Answer by alexdevAo · Feb 07, 2020 at 04:24 PM

You most call block.transform.localScale = new Vector3(XYZ, XYZ, XYZ); before Instantiate it It must be that way:

  public Gameobject block1
      
   for (int i = 0; i < 30; i++)
       {
       Vector3 rndVector = new Vector3(Random.Range(-2.55f, 2.55f), Random.Range(-1.6f, 4.1f), 0);
       float XYZ = Random.Range(0.27f,0.7f);
       block.transform.localScale = new Vector3(XYZ, XYZ, XYZ);
       GameObject block = Instantiate(block1, rndVector, Quaternion.identity);
      }

Comment
Add comment · Show 4 · 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 unity_ek98vnTRplGj8Q · Feb 07, 2020 at 04:34 PM 0
Share

No... block doesn't even exist yet if you move it before the instantiate I don't think this code will even compile

avatar image RigbySug · Feb 07, 2020 at 04:52 PM 0
Share

No not this way

avatar image alexdevAo · Feb 07, 2020 at 05:40 PM 0
Share

Try this way, create a new variable put blovkList name.Inspector put size 30. It also increases the distance from the Random Scale so that you can see the difference in size.

 public GameObject block1;
     public GameObject[] block1List;
 
     void Update()
     {
         for (int i = 0; i < 30; i++)
         {
             Vector3 rndVector = new Vector3(Random.Range(-5.55f, 5.55f), Random.Range(-4.6f, 7.1f), 0);
             block1List[i] = block1;
             GameObject tempBlock = block1List[i];
             float XYZ = Random.Range(0.01f, 1.0f);
             tempBlock.transform.localScale = new Vector3(XYZ, XYZ, XYZ);
             GameObject block = Instantiate(tempBlock, rndVector, Quaternion.identity);
         }
     }

Don't forget to assign the block1 gameobject in the inspector tab

avatar image RigbySug alexdevAo · Feb 07, 2020 at 06:24 PM 0
Share

Sorry but not like that too.

avatar image
0

Answer by Arnoldlove · Dec 24, 2020 at 11:35 AM

Instantiate can be used to create new objects at runtime. Examples include objects used for projectiles, or particle systems for explosion effects. Instantiate can also clone script instances directly. Prepaidcardstatus

Comment
Add comment · 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

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

238 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Trying to Clone 1 of 5 GameObjects in a array 1 Answer

Item Object Null When Spawned in as a Prefab Clone 1 Answer

Instantiate object at specific distance from transform position? 1 Answer

Creating a GameObject variable without instantiating it? 1 Answer

Int Value Not Randomizing 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