Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 MomijiStudios · Mar 04, 2014 at 10:55 PM · instantiatecirclegeometryareahole

Instantiate object in random position on 'donut' shaped platform

Basically I want objects to periodically instantiate in random positions on this platform. This wasn't a problem, because I just used the built-in "Random.insideUnitCircle." However, now I have a circular platform with a hole in the middle, and I do not want it to instantiate over the hole. Even worse, later on I have a platform with two holes in it.

I have a basic concept down: I have to subtract the area of that hole from the area of the entire platform, then spawn it somewhere in that area...I'm just not really sure how to go about that with the code. I could do it using loops to just constantly put a random spot until it is not a spot in that hole, but there HAS to be some way to do this using a simple line of Geometry.

Thank you in advance :)

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

2 Replies

· Add your reply
  • Sort: 
avatar image
3

Answer by SirCrazyNugget · Mar 04, 2014 at 11:20 PM

For one hole: Spawn at the center of the hole then pick a range angle and move a random distance from the minimum requirement to the maximum requirement forward

 var angle : float = Random.Range(0f, 360f);
 var dist : float = Random.Range(1f, 3f);
 
 transform.Rotate(Vector3(0, angle, 0));
 transform.Translate(Vector3(dist, 0, dist));

For two holes: I'll have to dig out an old book...

Comment
Add comment · Show 3 · 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 MomijiStudios · Mar 05, 2014 at 12:31 AM 0
Share

That's scary when someone says they have to 'dig out an old book' for a solution haha. Thank you very much, this makes a lot of sense.

avatar image levlaj · Jul 24, 2017 at 02:41 PM 0
Share

I like the way you think, for one hole this solution is the most elegant I can think of!

avatar image Alex_F · Feb 25, 2019 at 05:02 PM 0
Share

$$anonymous$$an, this is nice!

avatar image
0

Answer by robertbu · Mar 04, 2014 at 11:06 PM

Solving it with math is fairly straight forward, but since you are going to have two holes (and I assume the holes will not be in the center), why not figure out a solution that works for that situation now. One common approach is to just keep generating random values until you get one that works.

So here is an example:

 #pragma strict
 
 var holeLocalPos = Vector3(0,0);
 var holeRadius = 1.0;
 var platformRadius = 3.0;

 function FindPos() {
     var pos : Vector3;
     for (var i = 0; i < 1000; i++) {
         pos = Random.insideUnitCircle * platformRadius;
         if (Vector3.Distance(pos, holeLocalPos) > holeRadius) {
             return pos;
         }
     }
     return pos;
 }

FindPos() will return a valid local position. You will need to either add transform.position to the point (non-rotated or scaled platform), or use Transform.TransformPoint() to find the world position to spawn your object.

When you get two holes, just add a bit more data and change the check to:

     if ((Vector3.Distance(pos, holeLocalPos1) > holeRadius1) && (Vector3.Distance(pos, holeLocalPos2) > holeRadius2)) {

Note I use a for() loop that limits the tries. This prevents the code from hanging if I happen to code an impossible criteria. With the current code it would be difficult to hang, but imagine you add a new condition tomorrow that not only must it be on the ring, but the position must not overlap an existing object.

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 MomijiStudios · Mar 04, 2014 at 11:55 PM 0
Share

Thank you for the very thorough answer. I think I understand it, and I'll try to mess around with this.

This is kind of what I was already thinking though. I just feel like there's a simpler, more efficient way of doing this, through a geometric equation.

avatar image robertbu · Mar 05, 2014 at 12:08 AM 0
Share

For one hole, there are a couple of different approaches. @SirCrazyNugget solution is a good one. Same thinking but different approach would be:

 var localPos = Random.insideUnitCircle;
 localPos = localPos.normalzied * RandomRange($$anonymous$$Radius, maxRadius);

'$$anonymous$$Radius' and 'maxRadius' would be the inside and outside of your disk.

And I can think of a couple more, but they don't solve your two hole problem.

avatar image MomijiStudios · Mar 05, 2014 at 12:30 AM 0
Share

Okay, yeah that makes a lot of sense. But yeah, I suppose for the two holes the only real way to do it is with a loop.

First off, I'm using C# ins$$anonymous$$d of JS. I've always had a little trouble understanding Return and exactly what it does. I'd want that looping thing to be in a Coroutine so it wouldn't freeze the game up (which clearly you did because of the Return in there). What would the call from the main code look like for this Coroutine? I guess what I'm trying to say, is where exactly is that Returned value of 'pos' returning to?

avatar image robertbu · Mar 05, 2014 at 12:56 AM 1
Share

Here is a bit of C# code to put things in context:

 using UnityEngine;
 using System.Collections;
 
 
 public class Bug25a : $$anonymous$$onoBehaviour
 {
     public GameObject prefab;
     public Vector3 holeLocalPos = Vector3.zero;
     public float holeRadius = 1.0f;
     public float diskRadius = 2.5f;
 
     void Start() { 
         InvokeRepeating("Spawner", 0.0f, 1.5f);
     }
 
     void Spawner() {
         Vector3 pos = FindPos();
         pos += transform.position;
         Instantiate(prefab, pos, transform.rotation);
     }
 
     Vector3 FindPos() {
         Vector3 pos = Vector3.zero;
         for (var i = 0; i < 1000; i++) {
             pos = Random.insideUnitCircle * diskRadius;
             if (Vector3.Distance(pos, holeLocalPos) > holeRadius) {
                 return pos;
             }
         }
         return pos;
     }
 }

This code uses InvokeRepeating() rather than a coroutine. I ran this code with a small sphere as a prefab and the InvokeRepeating set to 0.01. After a $$anonymous$$ute this is the result:

alt text

randomring.jpg (143.3 kB)

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

22 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

Related Questions

Instantiate a Prefab with click in a certain area 2 Answers

Circle instantiate? 1 Answer

Instantiate GameObjects inside a collider 1 Answer

How can I spawn gameObjects within a circle radius? 1 Answer

Instantiate objects in a new position into a grid 1 Answer


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