Problem activate/ deactivate GameObject and array
Hi guys, I have weird problem.
I'm making a shooter game and pooling some missiles. This is the process:
Get the pooled missile;
this clone searches for enemies on screen;
Sets a random target and pursue it;
deactivate the target and missile itself (send them back to their own pools) ;
My problems are:
when I shoot a missile again (reactivate the missile) it moves to the "dead" enemy transform instead of search for new enemy. How can I make it search for new enemy?
if there are no enemies, I get an Exception "ArgumentOutOfRangeException: Argument is out of range.". It doesn't stop the game, but I'm afraid it can bring some trouble in the future.
Here is my Code:
void OnEnable()
{
SearchEnemyOnScreen();
}
//------------------------------------------------
void FixedUpdate()
{
if (isHazardOnScreen && hazardOnTarget != null)
{
LaunchMissile(hazardOnTarget.transform.position); // Homing Missile
}
else
{
MoveForward()
}
}
//------------------------------------------------
void OnTriggerEnter(Collider other)
{
if (other.tag == "Hazard")
{
other.gameObject.SetActive(false);
gameObject.SetActive(false);
isHazardOnScreen = false;
}
}
//------------------------------------------------
private void SearchEnemyOnScreen()
{
objOnScreen = FindObjectsOfType(typeof(GameObject)) as GameObject[];
List<GameObject> targetsOnScreen = new List<GameObject>();
foreach (GameObject enemy in objOnScreen)
{
if (enemy.tag == "Hazard")
{
targetsOnScreen.Add(enemy);
}
}
if (targetsOnScreen != null)
{
int randomTarget = UnityEngine.Random.Range(0, targetsOnScreen.Count - 1);
hazardOnTarget = targetsOnScreen[randomTarget];
isHazardOnScreen = true;
}
}
Answer by Jessespike · Mar 02, 2016 at 05:10 PM
When a list is created, it has 0 items. This is not the same thing as a list being null. You can add another condition in the search function:
if (targetsOnScreen != null && targetsOnScreen.Count > 0)
It is also important to note that Random.Range's max value for integers is exclusive, that means you don't need to subtract one from the max value.
Random.Range(0, 1) will always return 0.
Hi @Jessespike, thanks. This solved my "ArgumentOutOfRangeException" problem.
Can you also help me with my first problem, my missiles moving to an old spot ins$$anonymous$$d of search a new enemy?
I tried this: I added this lines to my FixedUpdate():
void FixedUpdate()
{
if (isHazardOnScreen && hazardOnTarget != null)
{
Launch$$anonymous$$issile(hazardOnTarget.transform.position); // Ho$$anonymous$$g $$anonymous$$issile
Debug.Log("Hazard on screen found by: " + gameObject.GetInstanceID());
}
else
{
$$anonymous$$oveForward();
Debug.Log("No hazards found by: " + gameObject.GetInstanceID());
}
And for my surprise I got a Log like this:
(!) Hazard on screen: -775606 // first shot, it found my unique enemy on screen and deactivated it.
(!) No hazards: -775606 // Second shot O$$anonymous$$, there were no enemies, so move forward
(!) Hazard on screen: -775624 // Third hot. Ops, a new instance is moving to the deactivated enemy gameobject transform.position
(!) No hazards: -775606 // Fourth shot O$$anonymous$$, as expected
// Then I reactivated my enemy gameobject an changed it position
(!) Hazard on screen: -775606 // Fifth shot O$$anonymous$$, found the new enemy GO and deactivated it again (Perfect)
(!) Hazard on screen: -775624 // Sixth shot. this instance is moving to the new deactivated enemy gameobject transform.position;
(!) Hazard on screen: -775636 // Same behavior as -775624
I don't understand why new clones are "inheriting" the first hazardOnTarget.position, and more, why they aren't doing the same when it is deactivated.
I'm not sure. I did notice that hazardOnTarget never gets set to null after deactivation, maybe that has something to do with it.
Answer by jorgeguimaraes · Mar 02, 2016 at 08:25 PM
You're right, I didn't set it to null, but my guess now is:
I instantiate 10 clones with my pooling script;
All 10 clones get the same enemy as target, because instantiating enables the object, even if the script immediately disables them;
my first missile clone hits the target, updates itself and "delete" it, so next time it's called it just moves forward;
while my first clone updates its list, the second don't, and my "Search" is called once inside OnEnable(), and unfortunately I don't have an OnActivate();
I will try to create a second script that:
search and spot a new target = myTarget;
get pooled object obj;
obj.MyMissileScript.SearchEnemyOnScreen(myTarget);
Am I on the right direction?