- Home /
Gameobject is destroyed even though I don't actively destroy it (or it's parent)
Hello guys,
I have found a weird behavior in my script where I get the follow error:
This is the stack trace: This is How I instantiate my "destroyed" object:
private void InitializeVitalBar(GameObject vitalsContainer, VitalType vitalType, Vector3 pos)
{
var bar = Resources.Load<FloatingVitalBar>($"UI/Vitals/Floating{vitalType.ToString()}");
var barInstance = Instantiate(bar, pos, Quaternion.identity);
Debug.Log(barInstance == null);
barInstance.Init(_context, _playerId, vitalType);
barInstance.transform.SetParent(vitalsContainer.transform);
}
And this is my object:
public class FloatingVitalBar : MonoBehaviour
{
private Guid _characterId;
private UnityEngine.Camera _mainCamera;
public Image ForeGroundHealthImage;
public Text HealthText;
public static FloatingDamage DamageObject;
void Awake()
{
_mainCamera = UnityEngine.Camera.main;
DamageObject = Resources.Load<FloatingDamage>("UI/FloatingDamage");
}
public void Init(IStateContext context, Guid characterId, VitalType vitalType)
{
_characterId = characterId;
var character = context.Selector.GetCharacter(_characterId);
Debug.Log(gameObject == null);
VitalUiUtils.InitializeVitalBar(vitalType, character, HandleHealthUpdate);
var vital = character.State.Vitals[vitalType];
var healthPercent = vital.CurrentValue / vital.MaxValue;
HealthText.text = $"{Mathf.RoundToInt(vital.CurrentValue)}/{Mathf.RoundToInt(vital.MaxValue)}";
ForeGroundHealthImage.fillAmount = healthPercent;
}
void LateUpdate()
{
transform.LookAt(_mainCamera.transform);
transform.Rotate(0, 180, 0);
}
private void HandleHealthUpdate(float healthPercent, float curValue, float maxValue, float damage)
{
Debug.LogWarning("HEALTH " + HealthText == null);
Debug.LogWarning("HEALTH IMAGE" + ForeGroundHealthImage == null);
//Debug.LogWarning("gameObject " + gameObject == null);
StartCoroutine(VitalUiUtils.UpdateBar(ForeGroundHealthImage, HealthText, healthPercent, curValue, maxValue));
// set the damage transform to follow the player
var instance = Instantiate(DamageObject, transform.parent.position, Quaternion.identity, transform.parent.parent);
// set the damage text to the calculated damage
instance.GetComponent<TextMeshPro>().text = Math.Ceiling(damage).ToString();
}
private void OnDestroy()
{
Debug.LogWarning("DDDDDDDDDDDDDESSSTROY");
}
}
}
OnDestroy does not print anything prior to the above exception it is only being called once I stop the editor
Any help is welcome :)
When exactly does the exception happen?
Also is it possible to post the stack trace from the error (the other text underneath it that list the calls prior to the error)?
Answer by xCeas · Feb 25, 2020 at 10:23 PM
So here is the cause of the problem:
public static void InitializeVitalBar(VitalType vitalType, ICharacter character, Action<float, float,float, float> updateMethod)
{
character.OnVitalModified += (vitalT, healthPercent, curValue, maxValue, change) =>
{
if (vitalType != vitalT)
return;
updateMethod(healthPercent, curValue, maxValue, change);
};
}
The above method (found in the attached stack-trace) registers my character to an object that is ultimately destroyed. I solved the problem by making my character Interface
also IDisposable
and when I destroy his gameObject
I carefully set all of the related events
on the character to null
.
Answer by Fragsteel · Feb 26, 2020 at 05:09 PM
It's hard to tell what's wrong from just looking at this, but here's a few things you can try. Note that none of it really makes sense if the object is truly never destroyed, so I'm going to work off the assumption that it is being destroyed, but in a way that's not immediately apparent.
Call StopAllCoroutines() in OnDestroy(). I have a feeling the stack trace mentions that StartCoroutine call because it's the closest it can get to actually telling you that the issue happened during a frame's invocation of the coroutine. I'm wondering if it's still going after the health bar is destroyed.
Comment out that coroutine and see if you still get the error.
Comment out the inside of the HandleHealthUpdate method (or just add
return
at the top) and see if you still get the error. If so, then the issue is with another script holding a reference to HandleHealthUpdate after it's been destroyed. It seems like you ruled this out already but this test would help us know definitively.
If that doesn't help, could you explain a bit more when exactly this happens? From the stack trace, it seems to happen after the character takes damage. But is it only when the damage causes the character to be destroyed?
Thanks for the answer!
I added some logs in between the calls of the stack trace, and I found that I have an event which points to the said destroyed object (to a character that is no longer available).
I will update with the full solution now that I found the cause
Your answer
Follow this Question
Related Questions
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
Instantiating prefabs: "The object of type GameObject has been destroyed". 1 Answer
Object reference not set to an instance of an object (with a RaycastHit) 3 Answers
Why Can't I Destroy This Object? 4 Answers
missing gameobject ≠ Null? 1 Answer