1
\$\begingroup\$

I am making 2D game with Unity. I want to create a procedurally generated background with a bunch of sprites (space background, I have sprites of nebulas and stars). I want some area around the player to be filled with sprites to some extent.

How to make background filling with sprites inside area around player but outside camera visible area?

How to control generation according to players movement for generating in player moving direction only?

How to control the amount of filling sprites while generating?

enter image description here

\$\endgroup\$
2
\$\begingroup\$

First you need a way to generate your star prefabs.

This is a simple code that creates your stars randomly:

using System.Collections;
using UnityEngine;

public class StarGenerator : MonoBehaviour {
    public GameObject Prefab;
    public Vector2 SpawnRange;
    public int SpawnNumber = 500;
    public float MaxiMaximumSize = 1f;


    private void Start()
    {
        GenerateStar();
    }
    public void GenerateStar()
    {

        for (int i = 0; i < SpawnNumber; i++)
        {
            var star = Instantiate(Prefab, new Vector2(Random.Range(0, 20f),Random.Range(0, 20f)), Quaternion.identity);
            float randomsize = Random.Range(0, MaxiMaximumSize);
            star.transform.localScale = new Vector2(randomsize, randomsize);
        }
    } 

}

enter image description here

then you can move star randomly. Remember, after a while, the circles are out of range,so you can Regenerate It by Destroying and Instancing again but Instead of this way you can use Object Pooling.

using System.Collections;
using UnityEngine;

public class Star : MonoBehaviour {
    public GameObject Prefab;
    private float randomMovement;

    /*public Vector2 SpawnRange;
    public int SpawnNumber = 500;
    public float MaxiMaximumSize = 1f;
    */

    private void Start()
    {

        randomMovement = Random.Range(1, 2f)*Time.deltaTime;
    }

    private void Update()
    {
        var horizontal = -Input.GetAxis("Horizontal");
        var vertical = -Input.GetAxis("Vertical");

        transform.Translate(new Vector2(randomMovement * horizontal, randomMovement * vertical));
    }

    /*
    public void Regenerage()
    {
       transform.position = new Vector2(Random.Range(0, 20f), Random.Range(0, 20f));
        float randomsize = Random.Range(0, MaxiMaximumSize);
        transform.localScale = new Vector2(randomsize, randomsize);
    }
    */
}

image

Also you can create procedural stars by shader or particle:

Star Nest

Star particles

\$\endgroup\$
  • \$\begingroup\$ How can you store Object type in var value? var star = Instantiate(Prefab, new Vector2(Random.Range(0, 20f),Random.Range(0, 20f)), Quaternion.identity); \$\endgroup\$ – Random generalist Mar 20 '18 at 12:37
  • \$\begingroup\$ @NikitaDemidenko The var keyword still declares a typed variable and it only works when you immediately assign a value to to variable. It also only works for local variables in C#. So only inside methods and not for class variables. It has no advantanges and is just a shorter way to declare a local variabl. Since you have to assign a concrete type when the variable is created it's usually clear what type it has. \$\endgroup\$ – Seyed Morteza Kamali Mar 20 '18 at 13:09
1
\$\begingroup\$

I would divide your world into a grid. If your sprites are N x N pixels (say 32 x 32), I would divide it up into a grid of cells that are each M x M sprites (say 5 x 5). At any position in the world, you can figure out what grid cell you're in by doing:

gridCell.x = floor(worldPosition.x / (M * N));
gridCell.y = floor(worldPosition.y / (M * N));

You can then use the grid position as a seed for a random number generator. Let's say that the x and y grid positions are 16-bit signed values and your random number generator takes a 32-bit seed. You could do something like:

seed = ((uint32_t)gridCell.x << 16) | ((uint32_t)gridCell.y)
randomSeed(seed);

Next, generate the index of which sprite to use using your random generator. The key here is to generate all of the sprite indexes in the current grid position every time so they always generate in the same order:

int i = 0;
for (y = 0; y < M; y++)
{
    for (x = 0; x < M; x++)
    {
        spriteIndex [ i ] = random(0, MAX_NUM_SPRITES);
        i++;
    }
}

Then you can fill in the current grid cell with the M x M sprites:

int i = 0;
for (y = 0; y < M; y++)
{
    for (x = 0; x < M; x++)
    {
        Draw(sprite[i], (gridCell.x * (M * N)) + x * N, (gridCell.y * (M * N)) + y * N);
        i++;
    }
}
\$\endgroup\$
  • \$\begingroup\$ I have some nebula sprites which I want to scale differently and rotate differently. Also, I wanna put them one on top another. I believe they hardly can fit with the grid. \$\endgroup\$ – Random generalist Mar 18 '18 at 7:50

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.