- Home /
self mistake
How to spawn only one GameObject from a list of game objects? Please help.
I writing a game where I need to create only two game objects at y location of say 3.0f and 4.0f at a time, and when both of them has been deactivated, I create another two at -3.0f and -4.0f.
The problem is whenever I call Spawn() once, they will create more than one game object, usually double the number I am creating. The location of the 'extra' game object is usually at the prefab's transform position (0, 0, 0), but not all the time. Here is the game object manager codes:
using UnityEngine;
using System.Collections.Generic;
using System;
using System.Linq;
namespace GameScripts.BalloonBalance {
public class starsManager_Bimanual : MonoBehaviour {
// Define if the stars need to be drawn or not (i.e. when the level is launched)
public static bool shouldDraw = false;
// Star pool
public List<GameObject> pool = new List<GameObject>();
// Bonus star pool
public List<GameObject> poolBonus = new List<GameObject>();
// Number of stars in the pools at the beginning
public int poolSize;
public int poolBonusSize;
public int currentPoolSize;
public int currentPoolSizeBonus;
// Total length of the level (world units)
public static float levelTotalLength;
// To know how many stars have already been created
public int starCount = 0;
void Awake() {
shouldDraw = false;
// Create and fill the pool
pool = new List<GameObject> ();
for (int i = 0; i < poolSize; i++) {
GameObject star = (GameObject)Instantiate (Resources.Load ("Prefabs/StarBimanual"));
star.transform.parent = transform;
star.GetComponent<StarBimanual>().manager = this;
star.SetActive(false);
pool.Add(star);
}
// Create and fill the pool (bonus=
poolBonus = new List<GameObject> ();
for (int i = 0; i < poolBonusSize; i++) {
GameObject star = (GameObject)Instantiate (Resources.Load ("Prefabs/BigStarBimanual"));
star.transform.parent = transform;
star.GetComponent<StarBimanual>().manager = this;
star.SetActive(false);
poolBonus.Add(star);
}
}
void drawFirstStars() {
Spawn (new Vector3 (0, 4.0f, 0));
Spawn (new Vector3 (0, 3.0f, 0));
shouldDraw = true;
}
void FixedUpdate () {
currentPoolSize = pool.Count;
currentPoolSizeBonus = poolBonus.Count;
if (shouldDraw) {
if (starCount >= LevelManager.currentLevel.levelLength) {
shouldDraw = false;
}
ReAddPool ();
}
else if (!shouldDraw) {
return;
}
Debug.Log (shouldDraw);
}
GameObject takeStarInPool() {
GameObject starToTake = pool [0];
pool.RemoveAt (0);
starToTake.SetActive (true);
return starToTake;
}
GameObject takeStarInBonusPool() {
GameObject starToTake = poolBonus [0];
poolBonus.RemoveAt (0);
starToTake.SetActive (true);
return starToTake;
}
void Spawn (Vector3 position) {
// Put normal star or bonus star depending on the bonus score
if (scoreBalloon.bonus > 0) { // Big star if bonus
takeStarInBonusPool ();
takeStarInBonusPool ().transform.position = position;
scoreBalloon.bonus--; // Remove the bonus
} else {
takeStarInPool ();
takeStarInPool ().transform.position = position;
}
starCount++;
}
public void Despawn (GameObject gameObject) {
gameObject.SetActive(false);
if (gameObject.GetComponent<StarBimanual> ().point == 1) {
pool.Add (gameObject);
} else if
(gameObject.GetComponent<StarBimanual> ().point == 3) {
poolBonus.Add (gameObject);
}
}
void ReAddPool(){
if (currentPoolSize == 10) {
if (starCount == 2 || starCount ==6 || starCount ==10 || starCount ==14 || starCount ==18 || starCount ==22 || starCount ==26) {
Spawn (new Vector3 (0, -3.0f, 0));
Spawn (new Vector3 (0, -4.0f, 0));
}
if (starCount == 4 || starCount ==8|| starCount ==12||starCount == 16|| starCount ==20||starCount == 24|| starCount ==28) {
Spawn (new Vector3 (0, 3.0f, 0));
Spawn (new Vector3 (0, 4.0f, 0));
}
}
}
void OnEnable() {
LevelManager.EnableLevel += drawFirstStars;
LevelManager.QuitLevel += stopDrawing;
}
void OnDisable() {
LevelManager.QuitLevel -= stopDrawing;
LevelManager.EnableLevel -= drawFirstStars;
}
void stopDrawing () {
shouldDraw = false;
}
public bool stopDrawing2 () {
shouldDraw = false;
return shouldDraw;
}
}
}
and here is the code for the game object prefab:
using UnityEngine;
namespace GameScripts.BalloonBalance {
public class StarBimanual : MonoBehaviour {
// Reference to the star manager (pooling)
[HideInInspector]
public starsManager_Bimanual manager;
// Number of points depend on the type of objects collected (to be filled in the inspector)
public int point;
// Information about the position, to reinitialize the stars
public Vector2 position;
public AudioClip starSound;
AudioSource source;
void Awake () {
source = Camera.main.GetComponent<AudioSource>();
}
// Update is called once per frame
void Update () {
DestroyUncollected ();
}
// Destroy collected stars
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.GetComponent<singleCharacter>() || other.gameObject.GetComponent<Character>()|| other.gameObject.GetComponent<Character_Bimanual>()) {
scoreBalloon.score += point;
source.PlayOneShot(starSound);
manager.Despawn(gameObject);
}
}
// Destroy uncollected star if out of the FOV
void DestroyUncollected () {
if (transform.position.x < Camera.main.transform.position.x - 4.0f) {
manager.Despawn(gameObject);
}
}
void OnEnable() {
LevelManager.QuitLevel += cleanStar;
}
void OnDisable() {
LevelManager.QuitLevel -= cleanStar;
}
// If a level is closed, all stars are put back in the pool
void cleanStar() {
manager.Despawn(gameObject);
}
}
}
Answer by Batka · Nov 15, 2016 at 11:14 AM
You call takeStarInBonusPool() more than once in Spawn.
Because it returns a GameObject, you call it twice just to refer to the star:
void Spawn (Vector3 position) {
// Put normal star or bonus star depending on the bonus score
if (scoreBalloon.bonus > 0) { // Big star if bonus
takeStarInBonusPool (); // <----- First Call
takeStarInBonusPool ().transform.position = position; <------- Second Call
The thing is, when you call it twice, it removes 2 stars from the pool, and SetsActive 2 stars as well:
GameObject takeStarInBonusPool() {
GameObject starToTake = poolBonus [0];
poolBonus.RemoveAt (0);
starToTake.SetActive (true);
return starToTake;
}
I'd suggest making this in two methods:
one as 'Getter', that will return the star as GameObject
the other as 'Setter', where the logic happens (poolBonus.RemoveAt(0) and starToTake.SetActive(true)
I hope this leads you somewhere
Tried that, not working. And finally what causing it is this line here:
void ReAddPool(){
if (currentPoolSize == 10) {
if (starCount == 2 || starCount ==6 || starCount ==10 || starCount ==14 || starCount ==18 || starCount ==22 || starCount ==26) {
Spawn (new Vector3 (0, -3.0f, 0));
Spawn (new Vector3 (0, -4.0f, 0));
}
if (starCount == 4 || starCount ==8|| starCount ==12||starCount == 16|| starCount ==20||starCount == 24|| starCount ==28) {
Spawn (new Vector3 (0, 3.0f, 0));
Spawn (new Vector3 (0, 4.0f, 0));
}
}
}
the second if statement (starCount 4 8) need to be else if! $$anonymous$$an that was unexpected.
Follow this Question
Related Questions
Checking if a position is occupied in 2D? 1 Answer
shrinking objects 1 Answer
How to assign a gameobject to a script that is added dynamically 1 Answer
Spawning GameObject contained within another 1 Answer
Spawn items around GameObject 3 Answers