Like for example in this image, they can randomly spawn outside of each others circle.
From my understanding, this could be done with Physics2D.CircleCast, or through checking if they are colliding with each other through a collider 2D. However, if I make the colliders bigger, they will just make the whole area be colliders, meaning for example a space ship can’t fly anywhere.
This is my code now, which spawns x number of objects in a radius around coords x/y -2, 2:
void Start()
{
for (int i = 0; i < numObjects; i++)
{
Vector3 position = new Vector3 (Random.Range (-2.0F, 2.0F), Random.Range (-2.0F, 2.0F), 0);
Instantiate (prefab, position, Quaternion.identity);
}
}
Your spaceship can’t fly through the stars? That’s an odd concept. Usually stars are background stuff. What exactly are you trying to do here? Are you trying to populate a single screen or have an infinite field of stars?
What you can do is create a double for loop (x and y) and add a random between 0 and 1 to the x and y in that those loops. You won’t have to check proximity then.
Black circles = objects
Green circles = hitbox / collider / raycast
Wouldn’t this be the easiest way of creating random patterns, but not overlapping patterns?
Because this way, the objects are prohibited from spawning if other objects (black dots) are inside their green circle.
All those physics circle casts are going to get expensive. I still need to know if this is going to be a single screen full or an infinite field of objects :-p
Not infinite at least, because that would crash the pc unless the stars have timers. I would like them to spawn randomly within a circle, so if the player-object moves forward, the circle spawns new randoms, while destroying the ones behind him / outside the circle.
That’s what I as afraid of. Instantiate and Destroy are very heavy methods. They create a ton of garbage and they will cripple your performance. You’ll get lags and stutters; there’s a good chance your game would be unplayable on certain devices. You’re gonna want object pooling. I sell a professional grade asset for 9.99 on the asset store, but there are others out there you may be able to pick up for free.
Of, that’s unfortunate. how should I handle this kind of spawning?
Maybe not relying on random spawning could be an idea, and just make the objects static. I’m pretty sure that would make the game a bit more boring, though.
Object pooling creates all the objects you are going to need at the start of the program and recycles them rather than making new ones. The API for most pooling solutions works by replacing Instantiate and Destroy with things like Spawn and Despawn. By recycling these objects you are able to eliminate a lot of garbage that would otherwise be generated nearly every frame by Instantiating new prefabs and Destroying old ones.
That’s not exactly how I would do it. You’ll be spawning more than you need there. I would spawn them in an area just slightly larger than the screen. My asteroid demo in Pool Master has a script for this done already.
I’m still unsure about how to create this spawning, though. I’m trying to read the Unity manual, but I have to admit I’m not a fast learner unless something is visual and/or with an example.
Let me consult my other script and see what I can do to help you out. The way my asteroid game works is the player stays stationary while the asteroids come down from the top. There’s an older version of the demo on my website if you follow this link: Sign in ・ Cloudflare Access
This is the script that controls the bulk of my asteroid game. Keep in mind that this script isn’t going to just work for what you need but it should at least give you some ideas on how to get where you need to go. Pay special attention to the where the asteroids are being spawned and how their position is being defined.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;
public enum AsteroidGameState {
Init,
Idle,
Spawn,
Wait,
Barrage,
BarrageWait,
Reset
}
public class AsteroidGameMaster : MonoBehaviour {
public AsteroidGameState _state;
private int _score;
private int _highScore;
private float _frequency = 1.5f;
private int _barrageChance = 5;
private float _barrageLength = 30.0f;
private float _barrageTimer = 0.0f;
private float _barrageFrequency = .25f;
private int _beltChance = 30;
private int _beltMax = 10;
private int _beltMin = 3;
private GameObject _title;
private GameObject _playerShip;
private Text _scoreText;
private Text _highScoreText;
// Use this for initialization
void Start () {
PoolMaster.PlayAudio("Music", true);
StartCoroutine ("GameController");
}
private IEnumerator GameController () {
while (true) {
switch (_state) {
case AsteroidGameState.Init:
Init ();
yield return new WaitForSeconds (5.0f);
break;
case AsteroidGameState.Idle:
Idle ();
yield return new WaitForEndOfFrame ();
break;
case AsteroidGameState.Spawn:
Spawn ();
yield return new WaitForEndOfFrame ();
break;
case AsteroidGameState.Wait:
Wait ();
yield return new WaitForSeconds (_frequency);
break;
case AsteroidGameState.Barrage:
Barrage ();
yield return new WaitForEndOfFrame ();
break;
case AsteroidGameState.BarrageWait:
BarrageWait ();
yield return new WaitForSeconds (_barrageFrequency);
break;
case AsteroidGameState.Reset:
Reset ();
yield return new WaitForEndOfFrame ();
break;
}
}
}
private void Init () {
_highScore = PlayerPrefs.GetInt ("HighScore");
_scoreText = GameObject.Find ("scoreText").GetComponent<Text> ();
_highScoreText = GameObject.Find ("highText").GetComponent<Text> ();
_highScoreText.text = "HIGH SCORE: " + _highScore.ToString ();
_playerShip = GameObject.Find ("playerShip");
_title = GameObject.Find ("asteroid_title");
_playerShip.SetActive (false);
_state = AsteroidGameState.Idle;
}
private void Idle () {
if (_title.activeSelf) {
_playerShip.SetActive (true);
_title.SetActive (false);
}
_state = AsteroidGameState.Spawn;
}
private void Spawn () {
if (Random.Range (0, 100) < _beltChance) {
int beltSize = Random.Range (_beltMin, _beltMax);
for (int i = 0; i < beltSize; i++) {
Vector3 tPos = new Vector3 (Random.Range (.1f, .9f), 1.15f, 0);
tPos = Camera.main.ViewportToWorldPoint (tPos);
tPos.z = 0;
PoolMaster.SpawnRandom (new string[]{"Asteroids"}, tPos);
}
} else {
Vector3 tPos = new Vector3 (Random.Range (.1f, .9f), 1.15f, 0);
tPos = Camera.main.ViewportToWorldPoint (tPos);
tPos.z = 0;
PoolMaster.SpawnRandom (new string[]{"Asteroids"}, tPos);
}
_state = AsteroidGameState.Wait;
}
private void Wait () {
if (Random.Range (0, 100) < _barrageChance)
_state = AsteroidGameState.Barrage;
else
_state = AsteroidGameState.Spawn;
}
private void Barrage () {
if (Random.Range (0, 100) < _beltChance) {
int beltSize = Random.Range (_beltMin, _beltMax);
for (int i = 0; i < beltSize; i++) {
Vector3 tPos = new Vector3 (Random.Range (.1f, .9f), 1.15f, 0);
tPos = Camera.main.ViewportToWorldPoint (tPos);
tPos.z = 0;
PoolMaster.SpawnRandom (new string[]{"Asteroids"}, tPos);
}
} else {
Vector3 tPos = new Vector3 (Random.Range (.1f, .9f), 1.15f, 0);
tPos = Camera.main.ViewportToWorldPoint (tPos);
tPos.z = 0;
PoolMaster.SpawnRandom (new string[]{"Asteroids"}, tPos);
}
_state = AsteroidGameState.BarrageWait;
}
private void BarrageWait () {
if (_barrageTimer < _barrageLength) {
_barrageTimer += _barrageFrequency;
_state = AsteroidGameState.Barrage;
} else {
_barrageTimer = 0;
_state = AsteroidGameState.Wait;
}
}
private void Reset () {
}
public void ModifyScore (int amt) {
_score += amt;
_scoreText.text = "SCORE: " + _score.ToString ();
if (_score > _highScore) {
_highScore = _score;
_highScoreText.text = "HIGH SCORE: " + _highScore.ToString ();
PlayerPrefs.SetInt ("HighScore", _highScore);
}
}
}
Interesting, I will look into it. I’m not sure how it would work in my case, because the stars/apples/objects in my game is stationary, meaning the player is the one moving. I’m sure I could change it so all the stars move instead, but I think it’s better as the player.