0

How would I create a non-uniform random generation of gameObjects (enemies) that mimic the formation of a "horde" like this image: enter image description here

I want there to be more gameObjects in the front and less as it trails off towards the back. I thought of making an Empty gameObject and having the enemies target with code like this:

public Vector3 target : Transform;
if (target == null && GameObject.FindWithTag("Empty"))
{
       target = GameObject.FindWithTag("Empty").transform;
}

However, doing that would not give me the "trail" effect where there are fewer int he back.

Here is my code for randomly generating enemies, if it helps:

void SpawnHorde()
{
    for (int i = 0; i < hordeCount; i++) 
    {
        Vector3 spawnPosition = new Vector3(Random.Range (0, 200), 50, Random.Range (0, 200));
        Instantiate(Resources.Load ("Prefabs/Sphere"), spawnPosition, Quaternion.identity);
    }
}

Does anyone have a suggestion as to how to achieve this?

My results after implementing @Jerry's code:

party in the front

More concentrated in the front; less in the back :)

crin
  • 73
  • 1
  • 2
  • 13
  • 2
    If you take above image and put in a X-Y axis system, you could go through the X coordinates stepwise from left to right, and have a function that tells for each X-coordinate or offset how many enemies to randomly spawn along the Y-line. E.g., have 10 enemies randomly spawn at `X=0`, then 7 at `X=1`, etc. Something like exponential falloff (`e^(-x)`) or linear falloff (`-ax + b`), quadratic maybe? The better you can mathematically describe the number of enemies on the Y-line as the X-coordinate progresses, the better results you get. – Maximilian Gerhardt Sep 27 '16 at 08:31
  • 1
    Random generates a random number within the range, and generally works out to be pretty evenly distributed over time within that range. You really want to be able to set the mean and standard distribution for the random numbers. I would check out [this question](http://stackoverflow.com/questions/18807812/adding-an-average-parameter-to-nets-random-next-to-curve-results?noredirect=1&lq=1) as the answer shows how to create this type of distribution for your x axis values. – Lithium Sep 27 '16 at 08:37
  • 1
    If you want some inspiration, you can take two linear functions (here `y = -2x + 100` and `y = 2x - 100`), that gives you the upper and lower boundaries for the y-positions of the enemies you want to spawn if `x = 0 to x = 50`. That gives you that nice "trail" you wanted. Now couple that sothat a lower x value means more enemies spawned and a higher x value means less enemies to be spawned (linear lerping? ;)) and you have your trail of enemies. (http://i.stack.imgur.com/FpdOd.png) – Maximilian Gerhardt Sep 27 '16 at 08:46
  • @MaximilianGerhardt thank you for the quick reply, that's a good idea, thank you. I'll have a go at that and see what I come up with. Ah and I didn't see your new reply until just now. I was going to mention to Lithium that I could actually use the system time in an equation to get my desired results. But wow thank you for taking the time to find an equation and everything. That seems easier actually – crin Sep 27 '16 at 08:47

1 Answers1

1

I would go for Maximilian Gerhardt suggestions. Here is some raw implementation, for you to tweak it as you want. The most important to tweak is positioning in one column, what you can achieve with some random numbers.

    void SpawnHorde()
    {
        int hordeCount = 200;
        float xPosition = 0;

        const int maxInColumn = 20;

        while (hordeCount > 0)
        {
            int numberInColumn = Random.Range(5, maxInColumn);
            hordeCount -= numberInColumn;

            if (hordeCount < 0)
                numberInColumn += hordeCount;

            for (int i = 0; i < numberInColumn; i++)
            {
                Vector3 spawnPosition = new Vector3(xPosition, 50, Random.Range(0, 100));
                Instantiate(Resources.Load("Prefabs/Sphere"), spawnPosition, Quaternion.identity);
            }

            xPosition += (float)maxInColumn * 2f / (float)hordeCount;
        }
    }
Jerry Switalski
  • 2,690
  • 1
  • 18
  • 36
  • Thank you! I tweaked a few things to my liking `zPosition += (float)maxInColumn * 20f / (float)hordeCount;` made it `20f` instead of 2f so they would be more spread out, and I also changed the direction they were oriented based on my terrain, hence `zPosition`. Right before I saw your answer I found my own solution by using `for` loops and decreasing the amount of objects in each loop depending on location, but I like your answer better! I'm going to edit my response with an attached image of the finished product. Thanks again – crin Sep 27 '16 at 09:42
  • @crin glad I could help! I saw your image - you can still play with the column positioning so the warriors won't be in same x - it looks now to generic. Cheers – Jerry Switalski Sep 27 '16 at 10:12