- Home /
When I destroy my gameObject my script Stops on working
when i destroy my game object after my enemy health is zero it will stop playing and will automatically exits the game it says the object of type "game object" has been destroyed but you are still trying to access it, how can i fix this ?. here's the code
public int maxHealth = 100;
public int curHealth = 100;
public GameObject Char;
public float HealthBarLength;
public bool EnmHealth;
// Use this for initialization
void Start () {
HealthBarLength = Screen.width / 3;
}
// Update is called once per frame
void Update () {
if (curHealth <= 0) {
Destroy(this.gameObject);
// Application.LoadLevel("MainMenu");
Char.animation.PlayQueued("Wrong answer",QueueMode.PlayNow);
//
PlayerPrefs.SetInt("SavedLevel1", 1);
Debug.Log("SavedLevel = 1");
//
}
AdjustCurrentHealth(0);
}
public void AdjustCurrentHealth(int adj) {
curHealth += adj;
if (curHealth < 0)
curHealth = 0;
if (curHealth > maxHealth)
curHealth = maxHealth;
if (maxHealth < 1 )
maxHealth = 1;
HealthBarLength = (Screen.width / 3) * (curHealth / (float)maxHealth);
}
void OnGUI() {
GUI.Box(new Rect(900, 10, HealthBarLength ,20), curHealth + "/" + maxHealth);
}
}
Answer by supernat · Feb 12, 2014 at 04:51 AM
When you destroy the game object, it destroys all child components, including the script.
Well I feel your pain, been stuck on critical problems that prevented me from moving forward and learning, so I'll try to help you out. A GameObject in Unity at its core is just a hierarchical Point. An empty game object, for instance, simply represents a 3D point in space. You can then add child game objects to that one to form child-parent relationships so that if you move the parent, the child follows, and if you rotate the parent, the child rotates around the origin of the parent (quite useful really).
You can add scripts in much the same way. Although you don't see the script outlined as a separate child game object in the Scene Hierarchy editor, it is attached closely to the game object such that if you delete it, it will be destroyed as well.
Don't think of the term "Destroy" as meaning "I killed an enemy". Destroy means removing the point and all children/scripts on it and below it from the game.
Now assume you are still trying to call a script on this game object that you have destroyed, which I believe is the case here. Then you are trying to ask a dead person to talk back to you. It just ain't gonna happen (well let's not get into that debate). In fact, the game crashes, because it doesn't know what to do. It just assumes you made a mistake. Imagine if it just went on its merry way and ignored your commands, how hard it would be to find those bugs. The crash is really a way to tell you to fix your logic. Your code is fine, but the logic is not. When you compile your game, the code syntax and form is being verified, but when you run it, things like this happen to prevent logic flaws (well also because the engine doesn't know what to do when you tell it to go run code that doesn't exist anymore).
So what is the solution? I kind of offered one in an earlier comment, but I'll clarify. You really shouldn't have the GUI code in a script attached to the enemy if you want to continue rendering the score GUI after the enemy dies. Create a new script that just renders the score, and attach it to an empty game object in your scene. Then add some static methods to update the score, like this:
public class ScoreRenderer : MonoBehaviour
{
public float HealthBarLength;
static public float score = 0;
void Start()
{
HealthBarLength = Screen.width / 3;
}
static public SetScore(float value)
{
score = value;
}
void OnGUI()
{
GUI.Box(new Rect(900, 10, HealthBarLength ,20), score.toString());
}
}
I simplified what you had to just displaying a single float value, but I want to make this as simple as possible, then you can get it working and complicate it from there. Now you have a nice simple score rendering class that you can attach to an empty game object, and from your EnemyScript, you would just call it like this:
ScoreRenderer.SetScore((float)curHealth / maxHealth);
The next thing you need to fix is stop calling AdjustCurrentHealth() externally. I assume you are calling it by reference? I mean, you have another script on a different game object (let's call it ScriptA), and you have dragged the Enemy game object onto that script over a public GameObject in the property inspector so that script can call this AdjustCurrentHealth method? If so, you need to fix that. Make it so that the script knows when the enemy is dead.
Again, for simplicity, just use a static variable, so in ScriptA:
public static bool enemyDead = false;
public GameObject enemyReference; // This is the public variable you drug the enemy game object onto in the editor (if you did)
void Update()
{
if (!enemyDead && SomeWeaponHitEnemyJustNow)
{
enemyReference.AdjustCurrentHealth();
}
}
Then in your EnemyScript, right after you check for health
ScriptA.enemyDead = true;
Hopefully this will get you on your way.
You can't. If you destroy a GameObject, you destroy the script. End of. What you can do is reorder it all so that destroying the GameObject is the last thing you do in that code section.
Technically, the game object isn't destroyed until end of the update loop, so it is probably safe to call methods on that game object in this frame though pointless. Your console should be giving you a line number for where you are trying to call this script still. I suspect something external is calling AdjustCurrentHealth. You should stop calling that. What exactly is your goal in needing to keep the script alive but not the game object, because you want the GUI score to remain? You could just disable the renderer component of the game object if you just want it to stop rendering, then destroy the GameObject with a timeout, Destroy(GameObject, 5) would destroy it in 5 sec for example.
aw the game object that i want to destroy is the enemy monster but when he gets destroyed i dont know but the game stops on working ins$$anonymous$$d of continuing
Where in the script do you tell it to destroy the enemy monster?
The meaning of this.gameObject
is perfectly clear, as should be the meaning of "x has been destroyed but you are still trying to access it"
Also "Char" is not an acceptable name for a GameObject variable.
Answer by RedDevil · Feb 12, 2014 at 10:16 AM
void Update () {
if (curHealth <= 0) {
Destroy(this.gameObject);
// Application.LoadLevel("MainMenu");
Char.animation.PlayQueued("Wrong answer",QueueMode.PlayNow);
PlayerPrefs.SetInt("SavedLevel1", 1);
Debug.Log("SavedLevel = 1");
//
}
You are trying to run an animation and do some calculations after you have already destroyed the game object.
Answer by Ashish Dwivedi · Feb 12, 2014 at 05:25 AM
Write your 24th line before 20th line.
Char.animation.PlayQueued("Wrong answer",QueueMode.PlayNow);
Destroy(this.gameObject);
I hope that would work...
`
that wont work after the game object is destroyed i dont know why but it exits the game
Your answer
Follow this Question
Related Questions
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
How to Destroy a gameobject on collision 3 Answers
How to delay lines of code. 2 Answers
Destruct gameobject by call from another script 1 Answer
When all objects with a certain tag has been destroyed, load the next level! 3 Answers