最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c# - Why is unity "randomly" making my objects nullstating that they are destroyed? - Stack Overflow

programmeradmin2浏览0评论

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;
        }
    }
}
发布评论

评论列表(0)

  1. 暂无评论