4

ScriptableObjects で MonoBehaviour コピー セマンティクスを模倣する方法はありますか?

次のような MonoBehaviour があるとします。

public class DummyClassBehaviour : MonoBehaviour {
    public DummyClass           DummyClassTest;     //ScriptableObject
    public DummyClassBehaviour  DummyBehaviourTest; //Another DummyClassBehaviour
}

そして ScriptableObject:

public class DummyClass : ScriptableObject {
    public string Text = "";
}

DummyClassBehaviour がアタッチされたゲームオブジェクトを複製 (CTRL+D) すると、「DummyBehaviourTest」は期待どおりにコピーします。新しいゲームオブジェクト。別のゲームオブジェクトの MonoBehaviour を参照する場合、その参照は変更されません。

一方、ScriptableObject は常にオリジナルを参照します。したがって、元のゲームオブジェクトから同じ ScriptableObject (DummyClass) を共有するNゲームオブジェクトがすべて終了します。ScriptableObjects を使用して、Monobehaviour 以外のデータ クラスのシリアル化を許可しています。

4

1 に答える 1

2

私の知る限り、間違っている場合は誰か訂正してください。MonoBehaviour のシリアル化動作と一致するように ScriptableObject のシリアル化動作を変更することはできません。つまり、重複が作成された場合は参照を更新する必要があります。

代わりに、最適ではないソリューションを選択しましたが、機能します。私のクラスには、他のすべてと同様にシリアル化される一意の識別子が割り当てられています。この ID を DummyBehaviour.Awake() で使用してルックアップ テーブルを作成し、それを使用して DummyClass を再割り当てします。

元の質問に完全に答えているとは思わないため、自分の答えを受け入れるつもりはありませんが、関連しています:

[System.Serializable]
public class DummyClass {
// Unique id is assigned by DummyBehaviour and is unique to the game object
    // that DummyBehaviour is attached to.
public int UniqueID = -1;
public string Text = "";

// Override GetHashCode so Dictionary lookups 
public override int GetHashCode(){
    int hash = 17;
        hash = hash * 31 + UniqueID;
    return hash;
}

    // override equality function, allows dictionary to do comparisons.
public override bool Equals(object obj)
{
    if (object.ReferenceEquals(obj, null))return false;

    DummyClass item = obj as DummyClass;
    return item.UniqueID == this.UniqueID;
}

    // Allow checks of the form 'if(dummyClass)'
public static implicit operator bool(DummyClass a) 
{
    if (object.ReferenceEquals(a, null)) return false;
    return (a.UniqueID==-1)?false:true;
}


public static bool operator ==(DummyClass a, DummyClass b)
{
    if (object.ReferenceEquals(a, null))
    {
         return object.ReferenceEquals(b, null);
    }

    return a.Equals(b);
}
public static bool operator !=(DummyClass a, DummyClass b)
{
    if (object.ReferenceEquals(a, null))
    {
         return object.ReferenceEquals(b, null);
    }
    return !a.Equals(b);
}
}

そして私のMonoBehaviour:

[ExecuteInEditMode]
public class DummyBehaviour : MonoBehaviour {
    public List<DummyClass> DummyClasses = new List<DummyClass>();

    // reassign references based on uniqueid.
    void Awake(){   
        Dictionary<DummyClass,DummyClass> dmap = new Dictionary<DummyClass,DummyClass>();
        // iterate over all dummyclasses, reassign references.
        for(int i = 0; i < DummyClasses.Count; i++){
            DummyClass2 d = DummyClasses[i];
            if(dmap.ContainsKey(d)){
                DummyClasses[i] = dmap[d];
            } else {
                dmap[d] = d;
            }
        }
        DummyClasses[0].Text = "All items same";
    }

    // helper function, for inspector contextmenu, to add more classes from Editor
    [ContextMenu ("AddDummy")]
    void AddDummy(){
        if(DummyClasses.Count==0)DummyClasses.Add(new DummyClass{UniqueID = 1});
        else {
            // Every item after 0 points to zero, serialization will remove refs during deep copy.
            DummyClasses.Add(DummyClasses[0]);
        }
        UnityEditor.EditorUtility.SetDirty(this);
    }
}
于 2013-03-12T00:04:23.373 に答える