Alternate idea instead of SendMessage

Hiya,
so I don’t know if it’s send message, or my receiving script but somewhere my numbers are occasionally being counted twice. I’ve looked through it many times, and i can only assume it’s based on the speed of my machine or that the messages are being sent but it’s happening and I don’t know how to stop it.
This is probably coded pretty much backwards but it’s working so I’m going with it for now…
I have a spaceship body with two wings, each wing has multiple guns, those guns need to be blown up individually before the ship will explode. On each gun I have this health script. When that gun gets destroyed it sends a message upwards that it’s gone, and a ticker counts down for that wing, if the ticker hits 0 the wing on that side gets the message to blow off. What I’m assuming is happening is the bullets are flying so fast the gun is registering it is at or under 0 HP multiple times and thus sending the message twice. which is being picked up twice and that gun is counted twice.

Gun Health Apply Damage Script

function ApplyDamage (damage : float)
{
	health -=damage;
	if (health <=0)
	{
	//un targetable by other weapons
		gameObject.tag = null;
	//turns off the barrel
		Gun.SetActiveRecursively(false);
	//explosion fx
		Instantiate(SegmentedExplosion, transform.position, transform.rotation);
	//creates smoke and links it to the wing, so when the wing floats off the smoke trails with it.
		var Smoke : GameObject;
		Smoke = Instantiate(SegmentedSmoke, transform.position+Vector3(0,0,-1), transform.rotation);
		Smoke.transform.parent = Wing.transform;
	//unparents the geo from the wing, parents it to the body and moves it off screen. This way all objects will disappear when the full ship blows up
		transform.parent = Geo.transform;
		transform.position=Vector3(0,100,0);
	//sends the message that this gun is destroyed.
		gameObject.SendMessageUpwards("PartDestroyed",side);
	}	
}

Section of the main ship that registers the “part destroyed” message.

function PartDestroyed(location:float){
parts--;
if(location==1)
	{
	Leftside--;
		if(Leftside<=0){
			BroadcastMessage("SIDE1");
		}
	}
if(location==2)
	{
	Rightside--;
		if(Rightside<=0){
			BroadcastMessage("SIDE2");
		}
	}
if (parts<=0){
BroadcastMessage("SIDE1");
BroadcastMessage("SIDE2");
BroadcastMessage("SIDE3");
yield WaitForSeconds(11);
Destroy(gameObject);
}
}

Everything works, just not fast enough. I know send message is slow, but I don’t know a way to direct cal weather specific guns have been destroyed or not. Any help would be awesome.

Ok, So I found a work around solution that seems to work but i don’t know if it’s the most ideal. I added a boolean variable called “Destroyed” and added this to the health script.

	if (health <=0  Destroyed==false)
	{
		Destroyed=true;

it seems like the boolean gets turned on before anything else and faster than the bullets are going so it is not calling the actions more than once.
But a more streamline idea would be great if someone has one.

Its possible your ApplyDamage script is getting called multiple times in the same frame, allowing it to retrigger when it is below zero health.

Try adding a check that you’re not already equal or below zero health at the top of your function. (before you subtract the damage)

Also, when weird stuff happens, use Debug.Log’s so you can see what’s happening! Often it makes these problems very simple to solve.

The most common question in this section is how to access a script from another. No need for sending messages or broadcasting.

So I came up with a better solution than sending messages and it was to put a boolean on every gun and use an array of the game objects for each section and put this code into the update function. if the boolean was true than it would be marked as true in this code.

if (
RightSide[0].GetComponent(E_Health_Segmented).Destroyed 
RightSide[1].GetComponent(E_Health_Segmented).Destroyed 
RightSide[2].GetComponent(E_Health_Segmented).Destroyed 
RightSide[3].GetComponent(E_Health_Segmented).Destroyed 
RightSide[4].GetComponent(E_Health_Segmented).Destroyed
)
{
RightSideExplode();
}

And that is working great, I´m wondering if there is a way of simplifying that and not using all those options? I tried something like

for(var o:GameObjects in RightSide)
{ 
     if (o.GetComponent(E_Health_Segmented).Destroyed) 
     { 
          objectsDestroyed = true; 
     } 
} 
 
if (objectsDestroyed) 
{ 
     // do something 
}

The nice part about this code is I can add as many game objects to the array and I don´t have to change the code. And that worked but it worked when ANY of the objects were destroyed.I only want it to go off if EVERY object is destroyed.

Any thoughts?

got it. I needed an “else” to turn it on.

for( var o : GameObject in RightSide) // Here replace "Object" with whatever type of RightSide is 
{ 
     if (o.GetComponent(E_Health_Segmented).Destroyed == false) 
     { 
          RightSideExploded = false; 
     }
          else
     {
     RightSideExploded = true; 
     }
}

Now no matter who many objects are in the right side array after they all blow up the right side is considered exploded