Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 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 Timebreaker900 · Mar 15, 2021 at 11:50 PM · classcustom editor

Unity Custom Class in Editor

Hi, I have a problem with saving a custom class in my binary system.


I have posted it on Stackoverflow aswell: https://stackoverflow.com/questions/66611904/unity-custom-class-in-editor

I have a problem with saving a custom class in my binary save system.

This is my SaveLoadManager.cs which does the binary saving:

 public static class SaveLoadManager 
 {
     private static string saveFileName = "/SpaceClicker.sav";
 
 
     public static bool Save(PlayerData data)
     {
         BinaryFormatter binaryFormatter = GetBinaryFormatter();
 
         FileStream stream = File.Create(Application.persistentDataPath + saveFileName);
 
         binaryFormatter.Serialize(stream, data);
 
         stream.Close();
 
         return true;
     }
 
     public static PlayerData Load()
     {
         if (!File.Exists(Application.persistentDataPath + saveFileName))
         {
             return null;
         }
 
         BinaryFormatter binaryFormatter = GetBinaryFormatter();
 
         FileStream stream = new FileStream(Application.persistentDataPath + saveFileName, FileMode.Open);
 
         try
         {
             PlayerData data = binaryFormatter.Deserialize(stream) as PlayerData;
             stream.Close();
             return data;
         }
         catch
         {
             Debug.LogErrorFormat("Failed to load file at {0}", Application.persistentDataPath + saveFileName);
             stream.Close();
             return null;
         }
     }
 
     private static BinaryFormatter GetBinaryFormatter()
     {
         BinaryFormatter binaryFormatter = new BinaryFormatter();
         return binaryFormatter;
     }




SaveLoadHandler.cs: In here I simply Save and Load.

In here is also my Custom Class "UpgradeClass" an my public variable factoryUpgradeClass which has the UpgradeClass.

 public PlayerData data;
 
     void Awake()
     {
         if (SaveLoadManager.Load() != null)
         {
             data = SaveLoadManager.Load();
         }
         
     }
 
     void Update()
     {
         SaveLoadManager.Save(data);
     }
 }
 
 [Serializable]
 public class UpgradeClass
 {
     public GameObject ob;
     public string upname;
 
     public bool bought;
 
     public UpgradeClass(GameObject ob, string upname, bool bought)
     {
         this.ob = ob;
         this.upname = upname;
         this.bought = bought;
     }
 }
 
 [Serializable]
 public class PlayerData
 {
    //Lots of values
    public List<UpgradeClass> factoryUpgradeClass;
 }



The Problem is when I start the game I get these 2 errors:
1. Error:

SerializationException: Type 'UnityEngine.GameObject' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at :0) System.Runtime.Serialization.FormatterServices+<>c_DisplayClass9_0.b0 (System.Runtime.Serialization.MemberHolder ) (at :0) System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at :0) System.Runtime.Serialization.FormatterServices.GetSerializableMembers (System.Type type, System.Runtime.Serialization.StreamingContext context) (at :0) System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo () (at :0) System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at :0) System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize (System.Object obj, System.Runtime.Serialization.ISurrogateSelector surrogateSelector, System.Runtime.Serialization.StreamingContext context, System.Runtime.Serialization.Formatters.Binary.SerObjectInfoInit serObjectInfoInit, System.Runtime.Serialization.IFormatterConverter converter, System.Runtime.Serialization.Formatters.Binary.ObjectWriter objectWriter, System.Runtime.Serialization.SerializationBinder binder) (at :0) System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write (System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo objectInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo memberNameInfo, System.Runtime.Serialization.Formatters.Binary.NameInfo typeNameInfo) (at :0) System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize (System.Object graph, System.Runtime.Remoting.Messaging.Header[] inHeaders, System.Runtime.Serialization.Formatters.Binary.__BinaryWriter serWriter, System.Boolean fCheck) (at :0) System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers, System.Boolean fCheck) (at :0) System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph, System.Runtime.Remoting.Messaging.Header[] headers) (at :0) System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize (System.IO.Stream serializationStream, System.Object graph) (at :0) SaveLoadManager.Save (PlayerData data) (at Assets/Scripts/DataSaving/SaveLoadManager.cs:22) SaveLoadHandler.Update () (at Assets/Scripts/Handlers/SaveLoadHandler.cs:33)



2.Error: IOException: Sharing violation on path C:\Users\mmorp\AppData\LocalLow\DefaultCompany\SpaceClicker\SpaceClicker.sav System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at :0) System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize) (at :0) (wrapper remoting-invoke-with-check) System.IO.FileStream..ctor(string,System.IO.FileMode,System.IO.FileAccess,System.IO.FileShare,int) System.IO.File.Create (System.String path, System.Int32 bufferSize) (at :0) System.IO.File.Create (System.String path) (at :0) SaveLoadManager.Save (PlayerData data) (at Assets/Scripts/DataSaving/SaveLoadManager.cs:20) SaveLoadHandler.Update () (at Assets/Scripts/Handlers/SaveLoadHandler.cs:33)


It refers to the line: "SaveLoadManger.Save(data)". The result is that the savefile cannot be loaded.

I searched a lot and maybe I need to do a custom editor? Can anyone help me out on that?

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
1

Answer by Bunny83 · Mar 13, 2021 at 11:42 AM

First of all:

I hope it is ok to just post a link? I just didn't want to post it twice.

No, that's not ok since answering a question that was asked on a third party website that could go down or the question over there could get deleted or changed it makes no sense to ask such questions, at all. We already had people asking questions here that had the essential bit of the question in images that were hosted on free hosters like imgur or tinypic. All those image links are dead now and the question useless.


So please copy your question over here into your question. You can edit your question at any time. Though please do keep the link to the SO question.


About your problem: Well you have several problems here. I'll try to state them in the order of "severity".


First of all your main issue is that your save data contains references to GameObjects. That is not possible at all and the reason why you get the first exception you mentioned. The BinaryFormatter can only serialize a whole object tree that includes all referenced instances. However you can not serialize a GameObject like that, at all.


The second exception you get is the result of the first one and the fact that you try to save your data once every frame. Since the Serialize call of the BF causes an exception your "SaveLoadManager.Save" method is terminated on the point which of course bubbles up to the Update method which is also terminated at the point. The result is that you never closed the filestream you created. Since the next frame you immediately try to save it again, you essentially try to open another file stream to the same file which is already open, so you get a sharing violation of the OS. You used a try catch in your load method but not in your save method. That's bad design ^^. Also you should always use a using statement for such things as it takes care of closing the stream no matter what.


Finally I highly recommend to stay away from the BinaryFormatter as Microsoft itself recommends. The BinaryFormatter is part of the remoting protocol of .NET and is meant to serialize parameters to RPC calls. It was never meant to serialize user data to files. It's also quite restrictive and verbose. Any change in the layout of your save class would break existing save files.


I highly recommend you aim for a human readable save format like json as it makes debugging easier. If you really want a binary format, you better roll your own using the BinaryWriter / BinaryReader. The resulting format would be much smaller and your code can decide what data you want to store and what not.


Since the data you want to save looks like it's a list of upgrades the user can buy, you usually have defined this list of upgrades in your project. The only information you want / need to store is if the user has bought it or not. If the list is more or less fixed you would only need an array of boolean values since the indices would usually not change. However it's usually better to store the upgrade name bundled with the "bought state" so you can individually react to removed or later added upgrades. At no point do you need or want to store the GameObject reference in a save file (which as I said is not possible and would not make any sense).

Comment
Add comment · Show 1 · 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 Timebreaker900 · Mar 15, 2021 at 10:37 AM 0
Share

First of all. Thank you very much for such an informative answer!

Yes you are absolutely right! I should post the whole question. I was a bit nervous because it was my first question.

If I change to something like json then it is easy to manipulate. And that is not what I what. Is there something else I could use besides binaryFormatter, which is not easy to manipulate?

Saving the bought state bundled with the name was a solution that I have already tried. I think I should give it a second chance. It looks like it's the simplest way for me to do it.

Thank you very much!

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

117 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 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

How to handle Serializable classes in a CustomEditor? 0 Answers

Custom editors for component/class attributes 1 Answer

Declare new class[].vector3[] length? 2 Answers

How to build up the class structure for an object 1 Answer

How do I change public variables depending on which level? 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