How to distribute prefabs evenly around a space in Unity2D?

31 Views Asked by At

Hello I am currently making a 2D topdown game in unity, in which I want to randomly generate trees and rocks throughout my map. Both are prefabs that you can interact with.

This is my current code. I spawn each prefab at a random position, but need to check that it has a distance of at least 10 to the nearest other prefab I spawned (so that the prefabs are evenly distributed):

void SpawnNature() 
    {
        for (int i = 0; i < 100; i++) 
        {
            Pos = new Vector3(Random.Range(-70, 70), Random.Range(-70, 70), 0);
            type = Random.Range(1, 3);
            distance = 100;
            GameObject nearestObject = null;
            float shortestDistance = float.MaxValue;
            foreach(GameObject Object in SpawnedObjects)
            {
                float dist = Vector2.Distance(Object.transform.position, Pos);
                if (dist < shortestDistance)
                {
                    shortestDistance = dist;
                    nearestObject = Object;
                }
            }
            distance = Vector2.Distance(nearestObject.transform.position, Pos);
            if (distance >= 10) {
                if (type == 1) {
                    Instantiate(rock, Pos, Quaternion.identity);
                }
                if (type == 2) {
                    Instantiate(tree, Pos, Quaternion.identity);
                }
            }
        }
    }

The problem is, I am getting a NullReferenceException on line 19. I think this is because something isn't working with finding the distance to the nearest prefab.

I would really appreciate any help. I am a novice programmer and really just want a solution to this. I know this is bad and inefficient code so whether you can fix this code, or have an entirely different approach, I would really appreciate your input!

Thanks a lot!

1

There are 1 best solutions below

1
Enfyve On

Consider first that nearestObject starts as null.

8:            GameObject nearestObject = null;

If you try accessing its .transform, it will throw an error.

8:            GameObject nearestObject = null;
//            ...
19:           distance = Vector2.Distance(nearestObject.transform.position, Pos);
//                                                     ^ NullReferenceException

From there you can work your way backwards:

  • The foreach loops through all of SpawnedObjects, so if there are none, it will throw.
  • In the first loop, dist will almost always be lower than shortestDistance (float.MaxValue) excluding some very unlikely scenarios.

So based on this, if you are getting an error, SpawnedObjects must be empty and you are not entering the foreach.

If it is the first object you're spawning, you likely won't have any SpawnedObjects, so you either need to spawn one before looping, or you need to find a different approach checking if nearestObject is null before accessing it. Don't forget to add the newly spawned object to SpawnedObjects either.

ps: If you're learning programming, try also taking time running your code through the debugger, step through so you can understand the logic and what leads to your errors. A better approach would be to not use GameObject or Transform and instead build an array of Vector2s and then when you're done, loop through that array instantiating your objects