Sometimes I can play my game the whole way through with no issues, pressing all the same buttons and running all the same code as other times (as far as I'm aware). However, sometimes I get an error that any sprite I click on "has been destroyed but [I'm] still trying to access it" but there seems to be no pattern to this behaviour.
I've searched every time that "Destroy" occurs across all my code and can't find a single circumstance where it would be destroying every sprite (my UI buttons are fine).
I understand on paper I obviously must just be destroying all of the sprites but I can't tell why it's happening so irregularly/"randomly" if that is the case. Additionally, when I do deliberately destroy my objects they are no longer visible on screen whereas in these circumstances they still are.
In the image's specific case, I had already reset the deck a few times with no issue despite resetting the deck causing the issue in other attempts at playing (with no code alteration since) but the error was caused here by the return face-ups Destroy (which also does not cause the issue every time).
I put print statements in after my Destroys (post copying the code into here) and it does seem to be both instances of calling Destroy that are causing it but I don't understand why a) the problem doesn't occur every time b) it is destroying cards whose parent's cards aren't tagged "DeckButton" in DealFromDeck c) the objects are still "destroyed" even though they are instantiated all over again
Here is every method that includes "Destroy" in my code.
Deal from deck:
public void DealFromDeck()
{
float xOffset = 1.7f;
string card;
UpdateSprite[] allCards = FindObjectsOfType<UpdateSprite>();
if (deckLocation < (deck.Count))//Can't increment it if at end of deck
{
card = deck[deckLocation];
}
else//Reset when at end of deck
{
//Erase deck button children
foreach (UpdateSprite allCard in allCards)
{
if (allCard.transform.parent != null)
{
if (allCard.transform.parent.CompareTag("DeckButton"))
{
Destroy(allCard.gameObject);
}
}
}
deckLocation = 0;
deckZOffset = 0;
card = deck[deckLocation];
}
GameObject newCard = Instantiate(cardPrefab, new Vector3(deckButton.transform.position.x + xOffset, deckButton.transform.position.y, deckButton.transform.position.z - deckZOffset), Quaternion.identity, deckButton.transform);
newCard.transform.localScale = new Vector3(15, 15, 0);
newCard.GetComponent<Renderer>().sortingOrder = deckLocation;
newCard.name = card;
newCard.GetComponent<Selectable>().faceUp = true;
deckLocation++;
deckZOffset += 0.02f;
}
Return face-ups (In my game the user can return all face-up cards to deck in order to reveal new ones)
public void ReturnFaceUps()//Button deckButton)
{
UpdateSprite[] cards = FindObjectsOfType<UpdateSprite>();
//Lose 20 points for a reset if not needed
if(!cantMove)
{
game.score -= 20;
}
//Put face up cards back into deck
foreach (UpdateSprite card in cards)
{
Selectable cardAttr = card.GetComponent<Selectable>();
if (!cardAttr.inDeck && cardAttr.faceUp)//Face up tableau cards
{
foreach(List<string> tableau in game.tableaus)
{
if (tableau.Contains(cardAttr.name))
{
tableau.Remove(cardAttr.name);
}
}
game.deck.Add(cardAttr.name);
}
}
//Reset deck offset
game.deckZOffset = 0;
//Delete all
foreach (UpdateSprite card in cards)
{
if (!card.CompareTag("DeckButton") && !card.CompareTag("Help") && !(card.name==("Card")))//Don't destroy deck button, help button or card prefab
{
Destroy(card.gameObject);
}
}
game.DealCards();
}
This doesn't have destroy in but it's what ReturnFaceUps calls and you can see it instantiates new objects anyway. Deal cards to tableau:
public void DealCards()
{
for (int i = 0;i<7;i++)
{
float yOffset = 0;
float zOffset = 0.03f;
int sortingOrder = 1;
foreach(string card in tableaus[i])
{
GameObject newCard = Instantiate(cardPrefab, new Vector3(tableauPos[i].transform.position.x, tableauPos[i].transform.position.y - yOffset, tableauPos[i].transform.position.z - zOffset), Quaternion.identity, tableauPos[i].transform);
newCard.name = card;
newCard.GetComponent<Selectable>().row = i;
//Set sorting layer and order for card
newCard.GetComponent<Renderer>().sortingLayerID = tableauPos[i].GetComponent<Renderer>().sortingLayerID;
newCard.GetComponent<Renderer>().sortingOrder = sortingOrder;
//Make bottom card face up
if (card == tableaus[i][tableaus[i].Count-1])
{
newCard.GetComponent<Selectable>().faceUp = true;
}
sortingOrder++;
yOffset += 0.5f;
zOffset += 0.03f;
}
}
}