0
\$\begingroup\$

My main character can move horizontally and not vertically. It can move from x = -4 to 4 and z = -4 to 4 (a square area). I don't want objects to spawn where my character can move but every where else.
I wrote the following script. According to me it should have worked perfectly fine. But, I can't figure out why the objects are still spawning in the perimeter where the main character is present.

public class SpawnGameObjects : MonoBehaviour
{
    public float secondsBetweenSpawning = 0.1f;
    public float xMinRange = -25.0f;
    public float xMaxRange = 25.0f;
    public float yMinRange = -5.0f;
    public float yMaxRange = 0.0f;
    public float zMinRange = -25.0f;
    public float zMaxRange = 25.0f;
    public GameObject[] spawnObjects; // what prefabs to spawn

    private float nextSpawnTime;

    void Start ()
    {
        // determine when to spawn the next object
        nextSpawnTime = Time.time+secondsBetweenSpawning;
    }

    void Update ()
    {
        // exit if there is a game manager and the game is over
        if (GameManager.gm) {
            if (GameManager.gm.gameIsOver)
                return;
        }

        // if time to spawn a new game object
        if (Time.time  >= nextSpawnTime) {
            // Spawn the game object through function below
            MakeThingToSpawn ();

            // determine the next time to spawn the object
            nextSpawnTime = Time.time+secondsBetweenSpawning;
        }   
    }

    void MakeThingToSpawn ()
    {
        Vector3 spawnPosition;

        // get a random position between the specified ranges
        spawnPosition.x = Random.Range (xMinRange, xMaxRange);
        spawnPosition.y = Random.Range (yMinRange, yMaxRange);
        spawnPosition.z = Random.Range (zMinRange, zMaxRange);
        if ((spawnPosition.z < 4 && spawnPosition.z > -4) || (spawnPosition.x < 4 && spawnPosition.x > -4)) 
        {
            MakeThingToSpawn ();
        }

        // determine which object to spawn
        int objectToSpawn = Random.Range (0, spawnObjects.Length);

        // actually spawn the game object
        GameObject spawnedObject = Instantiate (spawnObjects [objectToSpawn], spawnPosition, transform.rotation) as GameObject;

        // make the parent the spawner so hierarchy doesn't get super messy
        spawnedObject.transform.parent = gameObject.transform;
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ Well, there is a more tricky and easy way to spawn objects in 3D world. You may use this answer. \$\endgroup\$ Feb 13 '16 at 18:59
2
\$\begingroup\$

I think you problem is caused by continuing to execute the method when invalid position is generated:

//is position valid?
if ((spawnPosition.z < 4 && spawnPosition.z > -4) || (spawnPosition.x < 4 && spawnPosition.x > -4)) 
{
    //no -> call again
    MakeThingToSpawn (); //this will likely generate object at valid position
    //...and continue to execute this function after returning from function call above
    // spawning second object originally generated, at invalid position(!)
    return; //add return to quickfix to your problem - it will stop exectuing the rest of the function
}

also I would improve the method a bit - as for now it could(though unlikely) cause stack overflow, crashing the game. Again the problem is MakeThingToSpawn (); recursion. Rather then using recursion, I would translate the result to correct range, I would replace the code above with these two lines:

private static readonly double safeZoneSize = 4.0; //up in definitions
//greater than zero? add the safe zone size, subtract otherwise
spawnPosition.x += spawnPosition.x > 0 ? safeZoneSize : -safeZoneSize ; 
spawnPosition.z += spawnPosition.z > 0 ? safeZoneSize : -safeZoneSize ;

note: you need to compensate the safe zone size in the valid range definition(!)

\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.