Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by Comrad_Squirrel · Apr 05, 2018 at 02:47 PM · serializationscriptableobjectpolymorphism

How to make a deep copy of a list of ScriptableObject derived types?

The structure of my game is pretty unusual, so I'll give some context first. I'm working on a little puzzle / maze game, where pretty much every object can be moved / modified.

I handle this in the following way: every one of my objects inherits from a base class called RotatableObject, which in turn inherits from ScriptableObject (is required to use polymorphism when serializing assets). Then, using the scene view and a custom mapEditorScript, I can add objects of my choice to a list rotatableObjectList.

When hitting play, I can play the puzzle and after stopping, the puzzle resets, which is what I want (I have a script that translates the rotatableObjectList into prefabs that it instantiates). The problem starts when I save the map. I use another ScriptableObject derived class called Map, that contains a list of RotatableObject, and some other puzzle / map specific information. using:

Map newMap = ScriptableObject.CreateInstance(); newMap.map = new List (rotatableObjectList); ... AssetDatabase.CreateAsset(newMap,path); for (int i = 0; i < newMap.map.Count; i++) { AssetDatabase.AddObjectToAsset(newMap.map[i], path); } AssetDatabase.SaveAssets(); AssetDatabase.Refresh();

Saving and loading the map works, but after the map is saved, any changes that are made in play mode (by simply playing the game) are persistent, as the map ScriptableObject keeps being re-serialized. What I need is a to make a deep copy of the rotatableObjectList, and save that, so that the saved list is never changed, while the "active" in-game list can be.

I've looked at EditorUtility.CopySerialized(original, copy), but for this to work the original and the copy need to be of the same type, and I can't know the type of the RotatableObject derived class beforehand. Trying to find the type and then use it as a type (not as a variable) to create a copy object of the correct type led me to dynamic variables, which, if I understand correctly, are not implemented in Unity.

I can think of two other ways to make deep copies: one is to write a function that checks a given RotatableObject for the type by comparing it to all the possible derived classes in a long if else chain, and then returns an object of that type which can be used to copy the original object to.

Another solution could be to implement a Copy function manually in all the derived classes, which is responsible for creating a new instance of the class, giving in the correct parameters and then returning the new object.

Both of these methods seem error prone with respect to adding new objects, and involve writing extra code. So I was wondering, is there an easy way to make a deep copy of ScriptableObjects (of unknown type) that I'm not aware of? Or is there a clever way to use EditorUtility.CopySerialized(original, copy)?

Thanks in advance!

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
3
Best Answer

Answer by Bunny83 · Apr 05, 2018 at 02:59 PM

Well in general you can create a copy of any UnityEngine.Object derived class (which includes ScriptableObjects as well) by using Instantiate. However it depends on what you understand by "deep copy". It will clone all serializable class instances that the scriptable object might contain. However it won't clone any objects referenced by the serialized object which are UnityEngine.Object derived themselfs. So if your scriptable object references a material, GameObject, [ ... ] or another scriptable object the clone will also references those objects. If you want to create an instance of those as well you have to instantiate them manually.


Your question doesn't contain much details about your class and which types are involved so it's impossible to give any more detailed advice. If you need more information you should include your class declaration in your question.

Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Comrad_Squirrel · Apr 05, 2018 at 03:10 PM 0
Share

However it depends on what you understand by "deep copy". It will clone all serializable class instances that the scriptable object might contain. However it won't clone any objects referenced by the serialized object which are UnityEngine.Object derived themselfs.

This would be all I need. However, I was under the impression that Instantiate should not be used for creating ScriptableObjects, and that ScriptableObject.CreateInstance(Type type) should be used ins$$anonymous$$d. This is problematic for me as the type is not known beforehand, right?

avatar image Bunny83 Comrad_Squirrel · Apr 05, 2018 at 04:37 PM 0
Share

No, it's perfectly fine to use Instantiate with scriptableobject instances. CreateInstance just has to be used ins$$anonymous$$d of "new". Every UnityEngine.Object has a native code counterpart which is responsible for handling tracking and serialization of the object. Unfortunately Unity is not very consistant in this area. Some UnityEngine.Object derived classes can be created with "new" (like $$anonymous$$aterial, $$anonymous$$esh and even GameObject), others have to be created with a dedicated method. ScriptableObjects can only be created with CreateInstance and Components can only be created with AddComponent. However all those instances can be cloned with Instantiate. This cloning is done on the native code side of Unity where the actual data is serialized / deserialized.


Even if you want to create a new scriptableobject without copying any values you can use GetType() on an existing instance and use the returned System.Type object in CreateInstance.

avatar image Comrad_Squirrel Bunny83 · Apr 05, 2018 at 06:04 PM 0
Share

Thank you! That did the trick, and thanks for clearing up my confusion. It would never have occurred to me that instantiate could be used here.

Regarding using GetType(): I have not been able to figure out how it is supposed to work. I tried to use something like:
Type objectType = GetType(object); var newObject = ScriptableObject.CreateInstance(objectType);

where the object is also a Scriptable but I would always get the error "objectType is a variable but is used like a type" (even when using $$anonymous$$akeGenericType in between). Am I missing a step here?

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

81 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

ScriptableObject : Serialized Polymorphism Classes Can Not be Deserialize with Polymorphism 1 Answer

ScriptableObject asset loses reference after restarting Unity 1 Answer

[Solved]How to serialize Dictionary with Unity Serialization System 6 Answers

Difference between assigning a value in inspector and with a custom editor script 1 Answer

Serializing ScriptableObject into scene without writing to asset 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges