3

I am not sure how to approach this problem or whether there are any built in Unity functions that can help with this problem so any advice is appreciated.

Here is an image that'll help describe what I want to do: enter image description here

I want to spawn Game Objects around a given point within the limits of a set radius. However their position in this radius should be randomly selected. This position should have the same Y axis as the origin point (which is on the ground). The next main problem is that each object should not clash and overlap another game object and should not enter their personal space (the orange circle).

My code so far isn't great:

public class Spawner : MonoBehaviour {

    public int spawnRadius = 30; // not sure how large this is yet..
    public int agentRadius = 5; // agent's personal space
    public GameObject agent; // added in Unity GUI

    Vector3 originPoint;    

    void CreateGroup() {
        GameObject spawner = GetRandomSpawnPoint ();        
        originPoint = spawner.gameObject.transform.position;        

        for (int i = 0; i < groupSize; i++) {           
            CreateAgent ();
        }
    }

    public void CreateAgent() {
        float directionFacing = Random.Range (0f, 360f);

        // need to pick a random position around originPoint but inside spawnRadius
        // must not be too close to another agent inside spawnRadius

        Instantiate (agent, originPoint, Quaternion.Euler (new Vector3 (0f, directionFacing, 0f)));
    }
}

Thank you for any advice you can offer!

mwilczynski
  • 3,062
  • 1
  • 17
  • 27
Mayron
  • 2,146
  • 4
  • 25
  • 51
  • Spawning in circle is not a problem but tell me why are you not using colliders to maintain spaces? – Hamza Hasan Jan 08 '16 at 11:44
  • @HamzaHasan - I wasn't sure where to begin really. Colliders would be a good idea to detect if another agent entered another ones personal area but then how would I move one away from the other? At the moment each agent does not move. I just want to spawn them in a valid place when they spawn and not sure how colliders would help with that. – Mayron Jan 08 '16 at 11:47
  • Ok, let me do some work on it, tell me you are using 2D or 3D? – Hamza Hasan Jan 08 '16 at 11:57
  • wow thanks a lot. It's in 3D :) – Mayron Jan 08 '16 at 12:02
  • you are welcome :) Let me write your answer :) – Hamza Hasan Jan 08 '16 at 12:04

2 Answers2

7

For personal space you can use colliders to avoid overlapping.

For spawning in circle you can use Random.insideUnitSphere. You can modify your method as,

 public void CreateAgent() {
        float directionFacing = Random.Range (0f, 360f);

        // need to pick a random position around originPoint but inside spawnRadius
        // must not be too close to another agent inside spawnRadius
        Vector3 point = (Random.insideUnitSphere * spawnRadius) + originPoint;
        Instantiate (agent, point, Quaternion.Euler (new Vector3 (0f, directionFacing, 0f)));
    }

Hope this helps you.

Hamza Hasan
  • 1,368
  • 9
  • 17
  • Ah that's very simple. Thanks a lot. I've decided to use the NavMeshAgent since that has the ability to automatically make sure enemies do not collide with each other instead of using colliders. I hope that'll work. – Mayron Jan 08 '16 at 12:19
  • Man, you could make it clear in question that you want that sort of stuff :D – Hamza Hasan Jan 08 '16 at 12:20
  • I'm mainly using the NavMeshAgent for after the enemies have spawned. It doesn't really move them into the right place automatically when they spawn sadly. – Mayron Jan 08 '16 at 12:35
  • Oh and for the record I have only just thought about adding that in ^^ – Mayron Jan 08 '16 at 12:41
6

For spawning the object within the circle, you could define the radius of your spawn circle and just add random numbers between -radius and radius to the position of the spawner like this:

float radius = 5f;
originPoint = spawner.gameObject.transform.position;
originPoint.x += Random.Range(-radius, radius);
originPoint.z += Random.Range(-radius, radius);

For detecting if the spawn point is to close to another game object, how about checking the distance between them like so:

if(Vector3.Distance(originPoint, otherGameObject.transform.position < personalSpaceRadius)
{
    // pick new origin Point
}

I'm not that skilled in unity3d, so sry for maybe not the best answer^^

Also:

To check which gameobjects are in the spawn area in the first place, you could use the Physics.OverlapSphere Function defined here: http://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html

Michael Faisst
  • 597
  • 7
  • 20
  • That definitely helps me out thank you. I was thinking about randomly picking spawn locations until they don't overlap but that's extremely wasteful on processing as it might find it very hard to find a good location if I accidentally made the spawn radius too short. I'll check that function out :) – Mayron Jan 08 '16 at 11:50