Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
2
Question by kurotatsu · Sep 13, 2014 at 05:30 AM · serializationinventorysaveloadbinaryformatter

Bool array to binaryformatter method

I'm making an inventory asset for my game Voidkeeper( and to possibly sell on the asset store), and I'm running into a hitch saving bool arrays.

I know I can use ArrayPrefs2, but as I'm also learning a lot from the things I want to implement for uses in other functionality, I'd like help stepping through converting my bool array "equippedBools" to be serialized by binaryformatter, so bear with me.

I came across this example for a single bool:

PlayerPrefs.SetInt(Convert.ToInt32(someBool));

Now I'm trying to understand how to do it for an entire array, using binaryformatter.

(Mike Talbot, aka Whydoit, if you read this, know I thoroughly enjoyed your UnityGems Tutorial covering this subject.).;)

Here's a code snippet from my script where I am using a proxy bool array to set values in my Items class, which works btw, just need to save and load the bool array, rather than save my items class so I can keep their texture2D, and game objects intact.:

(I need the method to save and load for the bool array, as the snippet only shows an attempt for the item class.)

     public List<Items> itemsInGame = new List<Items>();
     private int itemInGameCount = 0;
     public bool[] equippedBools = new bool[]{};
 
 
 
     // Use this for initialization

     void Start() {

         //Clear equipment list.
         equippedList.Clear ();

         itemInGameCount = itemsInGame.Count;
         equippedBools = new bool[itemInGameCount];
 
         //Get the data
         var data = PlayerPrefs.GetString("EquipmentBools");
 

 //        //If not blank then load it
         if(!string.IsNullOrEmpty(data))
         {
             //Binary formatter for loading back
             var b = new BinaryFormatter();
             //Create a memory stream with the data
             var m = new MemoryStream(Convert.FromBase64String(data));
             
             //Load back the equipped values in all the Items in game.
             for(int t = 0; t < itemsInGame.Count; t++){
 
                 itemsInGame[t].equipped = b.Deserialize(m);
                 
             }
             
         }
 
         foreach(Items n in itemsInGame){
                 
             if(n.equipped == true){    
                     
                 equippedList.Add (n);
                     
             }
         }
 
 
         for(int t = 0; t < itemsInGame.Count; t++){
                 
             equippedBools[t] = itemsInGame[t].equipped;
             
         }
 
         foreach (bool value in equippedBools)
         {
             Debug.Log(""+ value);
         }

 void SaveEquipment () {
     
     //Get a binary formatter
     var b = new BinaryFormatter();
     //Create an in memory stream
     var m = new MemoryStream();
     //Save the equipment in equippedlist.
     b.Serialize(m, itemsInGame);
     //Add it to player prefs
     PlayerPrefs.SetString("EquipmentList", Convert.ToBase64String(m.GetBuffer()));

 }
 

 

Thanks for your time.

Comment
Add comment · Show 2
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 vexe · Sep 13, 2014 at 06:54 AM 1
Share

Format your code a bit better - the indentation is making it very hard to read it...

avatar image kurotatsu · Sep 13, 2014 at 03:14 PM 0
Share

sorry it was indented when I copy pasted I don't know what happened.

I went back and reformatted it for ya, once again I apologize.

1 Reply

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

Answer by vexe · Sep 13, 2014 at 06:51 AM

I would serialize the whole array to a string, and store that in the player prefs. Here's some extensions:

 public static class BinaryFormatterExtensions
 {
         /// <summary>
         /// Serializes 'value' to a string, using BinaryFormatter
         /// </summary>
         public static string SerializeToString<T>(this BinaryFormatter formatter, T value)
         {
             using (var stream = new MemoryStream())
             {
                 formatter.Serialize(stream, value);
                 stream.Flush();
                 return Convert.ToBase64String(stream.ToArray());
             }
         }
 
         /// <summary>
         /// Deserializes an object of type T from the string 'data'
         /// </summary>
         public static T DeserializeFromString<T>(this BinaryFormatter formatter, string data)
         {
              return (T)DeserializeFromString(formatter, data);
         }


         /// <summary>
         /// Deserializes the serialized string 'data' back to a raw untyped System.Object
         /// </summary>
         public static object DeserializeFromString(this BinaryFormatter formatter, string data)
         {
             byte[] bytes = Convert.FromBase64String(data);
             using (var stream = new MemoryStream(bytes))
                 return formatter.Deserialize(stream);
         }
 }

Usage:

 var input = new bool[] { true, false, true, true, etc };
 var serializer = new BinaryFormatter();
 var serializedData = serializer.SerializeToString(input);
 PlayerPrefs.SetString("Player Data", serializedData);
 // later on...
 string playerData = PlayerPrefs.GetString("Player Data");
 bool[] data = serializer.DeserializeFromString<bool[]>(playerData);

You can use these methods to [de]serialize anything, not just bool[] (except UnityEngine.Objects of course...)

EDIT:

So this way you could take a stream as a parameter when serializing so you could serialize to memory or file:

     /// <summary>
     /// Serializes 'value' to a string, using BinaryFormatter from the specified stream
     /// </summary>
     public static string SerializeToString<T>(T value, BinaryFormatter formatter, Stream stream)
     {
         using (stream)
         {
             formatter.Serialize(stream, value);
             stream.Flush();
             byte[] bytes;
             var ms = stream as MemoryStream;
             if (ms == null)
             {
                 var fs = stream as FileStream;
                 if (fs == null)
                     throw new NotSupportedException(string.Format("The type of stream: {0} is not supported", stream.GetType().Name));
                 bytes = File.ReadAllBytes(fs.Name);
             }
             else bytes = ms.ToArray();
             return Convert.ToBase64String(bytes);
         }
     

Notice it's a bit more complex because the base Stream class doesn't have a ToArray or ToBytes or something similar to read all the bytes so I first cast to a memory stream, if the cast is successful I use the ToArray otherwise I try file stream, if the cast is successful I read all the bytes from the original file's location (via the Name property) otherwise I throw an exception that the stream type is not supported (you might want to add other types of streams but memory and file are the most common) - Note you might wanna be careful when loading large files like that, not the best way.

Of course there's other ways to get the bytes, see this for instance. Up to you


EDIT: So here's how you go back and forth between bool[] and int - kinda fun:

     /// <summary>
     /// Ex: [true, true, false, false] ->
     ///      [1, 1, 0, 0] ->
     ///      12 (in decimal)
     /// </summary>
     public static int ToInt(this IEnumerable<bool> input)
     {
         var builder = new StringBuilder();
         foreach (var x in input)
         {
             builder.Append(Convert.ToByte(x)); // true -> 1, false -> 0
         }
         return Convert.ToInt32(builder.ToString(), 2); // 2 is the base - cause we're converting from base 2 (binary)
     }

     /// <summary>
     /// Credits: http://stackoverflow.com/questions/4448063/how-can-i-convert-an-int-to-an-array-of-bool
     /// </summary>
     public static bool[] ToBooleanArray(this int input)
     {
         return Convert.ToString(input, 2).Select(s => s.Equals('1')).ToArray();
     }

Usage:

 bool[] bools = { true, true, false, false };
 int n = bools.ToInt(); // 12
 foreach(var x in n.ToBooleanArray())
    Debug.Log(x); // true, true, false, false

Make sure to add using System.Linq; for the Select method

Comment
Add comment · Show 9 · 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 vexe · Sep 13, 2014 at 06:33 PM 1
Share

Sure glad to help. Not sure what you mean with "convert it to integer" - you mean the byte[] to integer? - well, an Int32 consist of 4 bytes so if you want to convert to an int you need to have an array of bytes with length of 4. See this. $$anonymous$$aybe I didn't get you. What's wrong with string?

avatar image vexe · Sep 14, 2014 at 06:02 AM 1
Share

$$anonymous$$y bad, corrected them. I was returning a raw object and taking no generic arguments. Added the generic version. The untyped version is also useful, sometimes you might not know the type of object you're returning at compile-time

avatar image vexe · Sep 14, 2014 at 06:11 AM 1
Share

You could take this further and let the serialization methods take a stream parameter as well so you could read/write from other resources such as files, etc. [Edit] added to answer

avatar image vexe · Sep 14, 2014 at 08:01 AM 1
Share

Added how you convert from/to int/bool[]

avatar image kurotatsu · Sep 14, 2014 at 02:32 PM 1
Share

Thanks vexe, these are very comprehensive answers, I wish I could give ya more upvotes, so I clicked every thumbs up I could find for ya on the page.lol

Well done.

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

24 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

Related Questions

SerializationException: End of Stream encountered before parsing was completed. 0 Answers

Saving gameobjects to .NET binary files 1 Answer

Get Asset at runtime by its ID 0 Answers

Serialize Data - After Update 1 Answer

Saving HashSet using BinaryFormat 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