2

i am trying to make some types of pickups spawn inside a given area, although some usually get stuck within the walls, how would i fix this?

Code in question for moving objects

for (int x = 0; x < garbage.Length; x++) 
{
    if (x < 5)
    {
        garbage[x].transform.position = new Vector3(Random.Range(-33.0f, 30.0f), 2.35f, Random.Range(30.0f, -35.0f)); 
    }
}

Fixed it using Physics.OverlapSphere. Thanks.

Ruben
  • 27
  • 2
  • 7

2 Answers2

0

You could have a while loop inside your if statement, so it would be like

int attempts = 0;
while(garbage[x].transform.position == /*[the range of coordinates for the wall]*/ || attempts = 0)
{
    garbage[x].transform.position = new Vector3(Random.Range(-33.0f, 30.0f), 2.35f, Random.Range(30.0f, -35.0f));
    attempts += 1;
} 
Tom Ryan
  • 397
  • 2
  • 6
  • 26
  • 1
    Don't do this. Using random number to control `while` loop is bound to cause your app to freeze. Maybe it's fine a coroutine function while yielding every frame but don't do it in a non coroutine function. – Programmer Jun 01 '18 at 14:11
  • @Programmer assuming this is an initial render of the world then a short freeze shouldn't be a problem, if it were to be a problem then yes a co-routine would be suitable: i'll edit my answer. – Tom Ryan Jun 01 '18 at 14:13
  • While loops are notorious for causing crashes, not just short freezes. Even when everything looks like it should work. In Unity it is best to avoid them. – Tyler S. Loeper Jun 01 '18 at 14:24
  • What's an alternative solution then? – Ruben Jun 01 '18 at 14:25
  • Why don't you use colliders. If your pickup spawns inside a collider with tag wall, then delete it and try and respawn it again on the next update. – Tyler S. Loeper Jun 01 '18 at 14:26
  • Is that not going to essentially be another while loop – Tom Ryan Jun 01 '18 at 14:27
  • Use update instead of while loops in Unity. Even if it has the same function. Or coroutine as stated by programmer. – Tyler S. Loeper Jun 01 '18 at 14:29
  • 1
    you can check for collisions before spawning using Physics.OverlapSphere – zambari Jun 01 '18 at 14:59
  • How would i achieve this using a physics.OverlapSphere @zambari – Ruben Jun 01 '18 at 16:01
  • You can check for collisons against a 'virtual' collider (which is what OverlapSphere does) without moving actual colliders, and without having to wait a frame for physics update. The method returns a list of colliders that overlap a virtual sphere with a center and radius you specify – zambari Jun 04 '18 at 07:20
0

You can try OnCollisionStay to tackle this with collisions. OnCollisionStay can be very cpu heavy if not used carefully, so you may want to think of a better way if you can.

You will have to create a new script using the following code, which you will attach to your power-up prefab.

bool keepChecking = true;
void OnCollisionStay(Collision collision)
{
    if(keepChecking)
    {
        if(collision.gameobject.tag == "Wall")
        {
            collision.gameobject.transform.position = new Vector3(Random.Range(-33.0f, 30.0f), 2.35f, Random.Range(30.0f, -35.0f));
        }
        else
        {
             keepChecking = false;
        }
     }
}

https://docs.unity3d.com/ScriptReference/Collider.OnCollisionStay.html

Read that link and make sure your objects have all the requirements. Your wall and Power-Up should have colliders, and at least one of these two should have a rigid body. None of these objects should be kinematic.

Let me know if this works for you.

Tyler S. Loeper
  • 816
  • 11
  • 22
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/172264/discussion-on-answer-by-tyler-s-loeper-moving-a-object-randomly-without-it-bein). – Andy Jun 01 '18 at 17:57