admin管理员组

文章数量:1418085

In my card game, I have a scriptable object that contains data about what cards the algorithm should place on its turn.

public class Structures : ScriptableObject
{
    public List<Card> Cards;
    public List<int> x;
    public List<int> y;
}

When it plays this structure using the "Prepare" behavior pattern, it copies the data into a separate variable at the beginning of the algorithm, then starts checking the first element of each list and deleting it on each turn.

private Structures playingStructure = null;
private void PlayPrepare()
{
    if(playingStructure == null)
    {
        int index = FindIndexOfStrutureByPatternIndex();
        if (index >= 0)
        {
            playingStructure = pattern.structures[index];
        }
        else Debug.LogError("index not found");
    }
    if(playingStructure != null)
    {
        try
        {
            gridManager.AddObjectToGridByAI(playingStructure.Cards[0], CardPrefab, (playingStructure.x[0] , playingStructure.y[0]));
            playingStructure.Cards.RemoveAt(0);
            playingStructure.x.RemoveAt(0);
            playingStructure.y.RemoveAt(0);
        }
        catch 
        {
            playingStructure = null;
            IsPlayingByTrigger = false;
            PlaceCards();
        }
    }
}

By deleting data from the playingStructure variable, the data is deleted from the original scriptable object.

Why? How do I copy data from a scriptable object so that it is not linked to the original?

In my card game, I have a scriptable object that contains data about what cards the algorithm should place on its turn.

public class Structures : ScriptableObject
{
    public List<Card> Cards;
    public List<int> x;
    public List<int> y;
}

When it plays this structure using the "Prepare" behavior pattern, it copies the data into a separate variable at the beginning of the algorithm, then starts checking the first element of each list and deleting it on each turn.

private Structures playingStructure = null;
private void PlayPrepare()
{
    if(playingStructure == null)
    {
        int index = FindIndexOfStrutureByPatternIndex();
        if (index >= 0)
        {
            playingStructure = pattern.structures[index];
        }
        else Debug.LogError("index not found");
    }
    if(playingStructure != null)
    {
        try
        {
            gridManager.AddObjectToGridByAI(playingStructure.Cards[0], CardPrefab, (playingStructure.x[0] , playingStructure.y[0]));
            playingStructure.Cards.RemoveAt(0);
            playingStructure.x.RemoveAt(0);
            playingStructure.y.RemoveAt(0);
        }
        catch 
        {
            playingStructure = null;
            IsPlayingByTrigger = false;
            PlaceCards();
        }
    }
}

By deleting data from the playingStructure variable, the data is deleted from the original scriptable object.

Why? How do I copy data from a scriptable object so that it is not linked to the original?

Share Improve this question asked Feb 4 at 18:24 kryakvakryakva 11 silver badge 0
Add a comment  | 

3 Answers 3

Reset to default 1

You could create a runtime clone using Instantiate

playingStructure = pattern.structures[index];
if(playingStructure)
{
    playingStructure = Instantiate(playingStructure);
}

Even better might be to rather do this only once wherever the list of those structures is stored.

Depending on thy type of Card and whether you modify that on runtime this might be not enough though.

Instantiate basically creates a "deep clone" so the lists will be copied and not linked to the original lists. However, any UnityEngine.Object references in this case (for ScriptableObjects) will remain the same. (For GameObjects only the external ones will remain while anything within the own hierarchy is replaced accordingly)

ScriptableObjects are references, so if you do something with them in code using editor, it will apply permamently (so after you stop the game, the changes will stay).

You can copy the data to normal object or instantiate a clone of your ScriptableObjects.

By the way - if you build the game it will work properly (ScriptableObjects will be ok after restarting the game).

Because when you run

playingStructure = pattern.structures[index];

This assign a reference by the original object to the variable playingStructure. Therefore, all operations on playingStructure are actually performed on the original object.

And as derHugo say,UnityEngine.Object.Instantiate can copy all Serializable data in ScriptableObject,But if you know what data will change,copy it manually like List<int> tx = new List<int>(playingStructure.x) ,performance is better.

本文标签: Unity copy data from scriptable object without linkStack Overflow