- Home /
,Having an issue accessing a destroyed object, can't figure out where the problem is coming from?
I've been trying to solve this for 2 days now and I can't figure it out. I have a buy menu (similar to csgo/valorant) that players can click and buy weapons. It works great, but if you get killed and you try to click a button to buy a weapon after you respawn, it gives me the error "MissingReferenceException: The object of type 'Player' has been destroyed but you are still trying to access it."
I'll throw some code in (all on player script) for context and hope someone can help me out!
Initializes Buy Menu and sets up the buttons, called on Awake.
private IEnumerator InitBuyMenu()
{
BuyMenu.instance.ToggleMenu();
GameObject buttonObj = GameObject.Find("BuyMenu/Buttons");
Button[] buyButton = buttonObj.GetComponentsInChildren<Button>();
for (int i = 0; i < buyButton.Length; i++)
{
int temp = i;
buyButton[i].onClick.AddListener(() => BuyPress(temp));
}
BuyMenu.instance.ToggleMenu();
Debug.Log("passed buymenu initialize");
yield return null;
}
The button press function that is called from the ienumerator
void BuyPress(int ind)
{
if(gameObject != null)
{
Weapon weaponController = GetComponent<Weapon>();
Debug.LogWarning("passed buypress command");
GunBuyButton.instance.BuyPress(weaponController, ind);
}
}
Gives me the error from the if(gameObject != null), obviously because the error says the gameObject (player) doesn't exist? I know what the issue is I guess? I just don't understand how to fix it.
If I had a guess, it's because it's attempting to still access the OLD player, and not the respawned clone prefab. I'm just not sure how to fix that?
Answer by Nicoup · Jun 16, 2021 at 11:52 PM
If I did not understand wrong, you are saying that when the player dies, you destroy its instance and for respawning you instantiate a new object. Could you provide the code of those two events ? Also, if you call a Debug.log at the beginning of the BuyPress function, is it called twice ?
Yes exactly. Calling the Debug.log within the IEnumerator shows up once at the start of the game, and then the Debug.log shows up once the first time a buy button is pressed from BuyPress, afterwards it doesn't even make it that far, again it stops and gives an error at the if(gameObject != null) line.
Also here is the code for respawning for you!
Take Damage part within Player script, called whenever the player takes damage obviously
public void TakeDamage(int p_damage)
{
current_health -= p_damage;
RefreshHealthBar();
if (current_health <= 0)
{
manager.Spawn();
Destroy(gameObject);
}
}
And then respawn part, within separate GameManager script, called at Start and when it detects player has died.
public void Spawn()
{
Transform t_spawn = spawnPoints[Random.Range(0, spawnPoints.Length)];
Instantiate(playerPrefab, t_spawn.position, t_spawn.rotation);
}
Small update, I tried the BuyPress function with nothing but the Debug.log. If I press a button before the player dies, it's called once. But if I press the button after the player dies and respawns, it's called twice? So I'm assu$$anonymous$$g the error is because it's accesses BOTH the new player, AND attempting to still access the dead/destroyed old player. I think I'm more confused :\
BuyMenu.instance.ToggleMenu();
Could you explain that line of code ? and why is it called twice ?
There is something wrong with your instances and its references, but I don't fully understand your project architecture . May I ask why do you destroy and instantiate the player for dying and respawning ? Isn't it better just to have a single instance of the player ? That would ensure your scripts will have always the same reference of the player.
Yeah I'm not sure tbh; I'm not the greatest at coding so it's probably pretty bad haha. I called it twice just to open and close the UI quickly just so it could find the buttons(hidden at start) and set them up but the player wouldn't be able to see.
I ended up scrapping the entire thing and rebuilding the buy system from scratch and ended up with something that was a LOT simpler and more importantly, actually works. Took your questioning for me to realize how bad the way I was doing it was so thanks lol
Answer by tuinal · Jun 17, 2021 at 06:10 AM
It looks like you're using a singleton pattern with 'instance'. Static variables persist between scenes.
The reason it's happening twice is when you reload the scene, you now have two (or more) managers, the one you made before the scene change, and the one you make every time the scene loads.
You need to handle it with an if(instance==null)...else{Destroy gameObject} type statement when you initialise the singleton in Start or Awake to auto-destroy any duplicates.
The scene is never reloaded though; the player prefab is just re-instantiated, no scene change. I'll try putting the if statement in however just in case
Your answer
![](https://koobas.hobune.stream/wayback/20220613035115im_/https://answers.unity.com/themes/thub/images/avi.jpg)