- Home /
Deactivating GameObject problem
I've just started implementing a Object Pooler for most of the gameobjects that I'm going to keep using such as enemies and effects. One of the things I'm trying to recycle is asteroids I have in my game and it seems to work fine. I have my asteroids spawning every so often and I have them move in random direction towards the screen view and then off using this code:
protected virtual void Start () {
direction = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0.0f, Camera.main.pixelWidth), Random.Range(0.0f, Camera.main.pixelHeight), Camera.main.nearClipPlane));
direction = direction - transform.position;
MoveInDirection();
}
It works fine. I also created a Entity class that all entities including asteroids inherit from and a function within that entity class makes it so objects are deleted if they are not visible anymore, I.E they go off screen. This worked perfectly before I implemented my object pooler since I used to just delete the objects if they went off screen but now I deactivate them to be used later.
The main problem with this is if you notice, I'm getting the direction and moving them in that direction in the Start function which doesn't seem to run if I deactivate and reactivate an object so the asteroids just stay still. I also added a feature so that the asteroids will spawn smaller asteroids after they've lost all their health. This worked perfectly also till the object pooler as asteroids have no health after being deactivate and reactivate and so they can be one shot. The smaller asteroids also don't seem to spawn always and I'm spawning them using a object pooler too.
This is the code that is causing the problem:
protected virtual void Update()
{
if(!GetComponent<SpriteRenderer>().isVisible)
{
beyondScreenTimer += Time.deltaTime;
if(beyondScreenTimer >= beyondScreenDelay)
{
objectPooler.DestroyPooledObject(gameObject);
}
}
}
The DestroyPooledObject() refers to this method within my object pooler script:
public void DestroyPooledObject(GameObject obj)
{
pooledObjects.Add(obj);
obj.SetActive(false);
}
I'm also reactivating the pooled objects with this method:
public GameObject InstantiatePooledObject(GameObject objPrefab)
{
for(int i = 0; i < pooledObjects.Count; i++)
{
if(!pooledObjects[i].activeInHierarchy && pooledObjects[i].gameObject.name == objPrefab.name + "(Clone)")
{
pooledObjects[i].SetActive(true);
return pooledObjects[i];
}
}
GameObject obj = Instantiate(objPrefab) as GameObject;
obj.SetActive(true);
obj.transform.SetParent(transform);
pooledObjects.Add(obj);
return obj;
}
I've been trying to figure out a way to fix this problem but I can't think of a way unless I am able to reset the game objects but still have all their values so their movement speed and damage for example. I haven't used my object pooler for enemies yet but I imagine it will be the same case for the enemies so I was wondering if someone would be able to help?
It seems the problem for some reason is the smaller asteroids are spawning but not activating and I'm not sure why since I am telling them too.
Answer by Codelyy · Aug 03, 2016 at 10:24 PM
I have figured out the problem and I can't believe I didn't realise .
Within the Entity Script I created:
protected virtual void Update()
{
if(!GetComponent<SpriteRenderer>().isVisible)
{
beyondScreenTimer += Time.deltaTime;
if(beyondScreenTimer >= beyondScreenDelay)
{
objectPooler.DestroyPooledObject(gameObject);
}
}
}
I have a variable called beyondScreenTimer that will count up to beyondScreenDelay and then deactivate the gameobject. Because I wasn't ever resetting the beyondScreenTimer back to 0f, if beyondScreenTimer was above or equal to beyondScreenDelay... It would just keep deactivating the gameobject
Answer by Ma_ti · Aug 03, 2016 at 07:41 PM
void Start () will get called only once no matter if you reactivate it, you should try void OnEnable() for this
I have started using OnEnable and that has fixed the non-moving problem but not the small asteroid problem. Smaller asteroids are meant to spawn everything time the asteroid is destroyed and it works the first 2 times for example if I destroy the asteroid, reactivate it and then destroy it again but then it goes from spawning 2 smaller asteroids to spawning 1 and then it doesn't spawn any.
It seems the smaller asteroids are not always beco$$anonymous$$g active when I want them too.
Can you show the part with activating/spawning these small asteroids?
This is what I use to get pooled objects from a list to activate them:
public GameObject InstantiatePooledObject(GameObject objPrefab)
{
for(int i = 0; i < pooledObjects.Count; i++)
{
if(!pooledObjects[i].activeInHierarchy && pooledObjects[i].gameObject.name == objPrefab.name + "(Clone)")
{
pooledObjects[i].SetActive(true);
return pooledObjects[i];
}
}
GameObject obj = Instantiate(objPrefab) as GameObject;
obj.SetActive(true);
obj.transform.SetParent(transform);
pooledObjects.Add(obj);
return obj;
}
This is how I spawn the smaller Asteroids:
void OnTriggerEnter2D(Collider2D target)
{
if(target.tag == "Projectile")
{
Destroy(target.gameObject);
health--;
if(health <= 0)
{
DestroyBigAsteroid();
}
}
public void DestroyBigAsteroid()
{
print("Calling Script");
Vector2[] directions = new Vector2[8]
{
Vector2.right,
Vector2.up,
Vector2.down,
Vector2.left,
(Vector2.left - Vector2.down).normalized,
(Vector2.left + Vector2.up).normalized,
(Vector2.right - Vector2.down).normalized,
(Vector2.right + Vector2.up).normalized,
};
Vector2 randomDirection = directions[Random.Range(0, directions.Length)];
objectPooler.DestroyPooledObject(gameObject);
GameObject mAsteroid1 = objectPooler.InstantiatePooledObject(mediumAsteroid);
mAsteroid1.transform.position = transform.position;
mAsteroid1.GetComponent<Rigidbody2D>().AddForce(randomDirection * 1200, Force$$anonymous$$ode2D.Impulse);
GameObject mAsteroid2 = objectPooler.InstantiatePooledObject(mediumAsteroid);
mAsteroid2.transform.position = transform.position;
mAsteroid2.GetComponent<Rigidbody2D>().AddForce(-randomDirection * 1200, Force$$anonymous$$ode2D.Impulse);
GameObject explosionObj = objectPooler.InstantiatePooledObject(explosion);
explosionObj.transform.position = transform.position;
objectPooler.DestroyPooledObject2(explosionObj, 1);
//30% Chance of spawning Extra Life
if(Random.value <= 0.3f)
{
SpawnExtraLife();
}
}
try puting this middle line
mAsteroid1.transform.position = transform.position;
mAsteroid1.GetComponent<Rigidbody2D>().velocity = Vector2.zero;
mAsteroid1.GetComponent<Rigidbody2D>().AddForce(randomDirection * 1200, Force$$anonymous$$ode2D.Impulse);
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Trouble with resetting the score with button 1 Answer
Illuminating a 3D object's edges OnMouseOver (script in c#)? 1 Answer