Spawning object at random, collision-free position

Hello, Is there any way to make an object "scan" a certain area (like a circle around him) and then spawn at a random position within that area that is free of collisions? Imagine as if it's a wizard teleporting around the screen. Note that this is for a 3D game.

Also, say I want this object to spawn on elevated platforms and even on the vertical sides of walls as well. How would I handle that?

You could do this by checking the spherical area around the target position first, using Physics.OverlapSphere.

Eg:

var checkResult = Physics.OverlapSphere( targetPosition, checkRadius );
if (checkResult.Length == 0) {
    // all clear!
    Instantiate( wizardPrefab, targetPosition, Quaternion.identity );
}

Note however that OverlapSphere only tests against the bounding boxes of other colliders, so if you are using complex scenery objects with mesh colliders, this solution probably won't work for you.

As a more accurate alternative, you could create a special "Teleport Tester" prefab. This would be an invisible GameObject, with a sphere collider attached, but that sphere collider should be set to isTrigger = true. It should have a script on it which sets a boolean flag as to whether any collisions have occurred. Call the script "TeleportTester". Eg:

// -- TeleportTester.js -- 
var allClear = true;

function OnCollisionEnter() {
    allClear = false;
}

You could then instantiate this "Teleport Tester" prefab first, then allow one physics update step to elapse (using WaitForFixedUpdate), then test the "collided" variable to see whether any collisions were reported. If not, then you can instantiate the real wizard object in that position. You would of course want to Destroy() your tester instance afterwards too. Something like this:

var testerPrefab : TeleportTester;  // drag tester prefab into this var
var wizardPrefab : Wizard;    

function TeleportWizard( targetPos : Vector3 ) : Wizard {

    // test whether the target area is all clear:
    var tester = Instantiate( testerPrefab, targetPos, Quaternion.identity );
    yield new WaitForFixedUpdate();

    if (tester.allClear) {
        // all clear for wizard to appear!
        var wizard = Instantiate( wizardPrefab, targetPos, Quaternion.identity );
        return wizard ;
    } else {
        // maybe the calling function should pick a new spot and try again
        return null;
    }
}

Hope this helps!

(usual disclaimer - code untested, for illustrative purposes only)

Thanks for the reply. I'll try it out sometime. However, I've been looking into the scripting references, Raycasting in particular.

I've thought about the following possible solution: - Cast out rays in a sphere around the object. - Store the ones that collided and are within a certain distance into an array. - Randomly pick a position from this array and then use Physics.CheckSphere (a little "above" the position) to see if it's free. - If so, mark it as a teleport position, if not choose a new random position from that previous array.

I've never worked with raycasting before though. Do they work on MeshColliders? Do they pass through character/enemy objects? How would I handle casting them out in a sphere (I imagine I would need some mathematical formula)? Would this method not be too tasking on the CPU?

Would be nice if you (or anyone else) could answer those questions and/or point out if my proposed method could work or if it would be impractical.

@duck Hi I know this thread is really old but I came across it when trying to spawn in GameObjects without being stuck in one another. So my question is how would one do the first method in a for loop? I am really new to unity so i’m having a though time with this concept.

I would go about it by teleporting a trigger object around the area (using Random.Range in the coordinates) and if it collides, try again. If it doesn’t collide, then that area is clear and then teleport the wizard.