Using Resources.Load on my binary data to create a custom asset actually doubles its size

I have some custom binary data stored into a file myData.bytes.
I can import this data to create a custom assets as follows:

TextAsset myTextAsset  = Resources.Load( pathToMyDataWithoutTheBytesExtension) as TextAsset;
MyAssetType myAsset.bytes = myTextAsset.bytes;
AssetDatabase.CreateAsset( myAsset, assetPath);
AssetDatabase.SaveAssets();

MyAssetType is a ScriptableObject type. It is an asset that contains (binary) information to be loaded into custom native plugin i am working on.
This code actually works. It properly saves a myAsset.asset file.

My problem is that myAsset.asset file is always twice the size of the original myData.bytes. For instance if the original myData.bytes is 16KB then my saved myAsset.asset will be 32KB or so. I am guessing that this has to do with the fact that text encoding in unity must be unicode and thus use 2 bytes? So each original byte “char” in myData.bytes gets encoded as a 2 bytes “unicode char” in txt.bytes?

Is there a proper way to import binary data and save it to an asset with the same size? Maybe involving converting to ascii?

I’m not quite sure what you’re asking here. We don’t know what “MyAssetType” actually is. Since you store it as asset we would assume that this is a ScriptableObject type? You know that Unity’s “.asset” format is usually just YAML text? So your byte array would be stored as a stream of hexvalues. Something like this:

%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
  m_ObjectHideFlags: 0
  m_CorrespondingSourceObject: {fileID: 0}
  m_PrefabInstance: {fileID: 0}
  m_PrefabAsset: {fileID: 0}
  m_GameObject: {fileID: 0}
  m_Enabled: 1
  m_EditorHideFlags: 0
  m_Script: {fileID: 11500000, guid: 669bc2d8c6369f145b428260cea98177, type: 3}
  m_Name: SerializeTestScriptableObject
  m_EditorClassIdentifier: 
  data: 02ff0405800840080706

Note that this is an asset file of a ScriptableObject that looks like this:

using UnityEngine;

[CreateAssetMenu]
public class Test : ScriptableObject
{
    public byte[] data;
}

The asset I created has a byte array with 10 values, specifically 2, 255, 4, 5, 128, 8, 64, 8, 7, 6. As you can see the data is stored as a hex stream 02ff0405800840080706. Of course hexadecimal encoding will exactly double the size.

However this is just the asset file inside your project. When you build your game the assets are usually stored in the binary asset format. So you shouldn’t pay too much attention to the source asset files in your project. Check the build report when you create a build of your game.

Apart from actually importing and storing your binary data in Unity’s asset format you can of course just ship your binary data seperately. One way is to use the StreamingAssets folder. Though note that on Android and WebGL builds you don’t have direct file access to this folder. Instead you have to use a UnityWebRequest to read the content of the file. On most other build platforms the streaming assets folder is an actual folder and the files in it are shipped as they are so you can access them by the usual file io routines (System.IO). For more information see Application.streamingAssetsPath and the manual on StreamingAssets

edit

Note I just expanded the array to 16000 bytes, saved the scriptable object and created another build. The scriptable object asset in my resources folder has a size of a bit over 32k. This is what the asset looks like in the build report:

15.7 kb    0.0%    Assets/Resources/SerializeTestScriptableObject.asset

Note that 16000 when divided by 1024 you get 15.625. Since the size is rounded to the closest 100 bytes the difference is probably the overhead of the other asset meta data which you saw in the yaml above. However in the binary format for shipping only the essential parts are included.

Also note that the size specified in the build report is the uncomressed size. Assets and resources are often even compressed when you build your game. Though that depends on the target platform.

This is the part of the actual compiled “resources.asset” file in my standalone build. I’ve highlighted the actual byte data I put into the byte array:

As you can see there’s a tiny binary header for each asset in the asset file. The actual data in this case is uncomressed. When I expanded the byte array from 10 to 16000 bytes, the last byte got duplicated (the usual inspector behaviour which just duplicates the last value when you expand the size). That’s why all values are just “06”. The “803E0000” before the data is the actual length of the data in little endian (so it’s 0x3E80 which is exactly 16000)

To see the build log you just have to look into the editor log. To open it just click the window menu of the console window at the top right corner of the console and select “Open Editor Log”. Search for “Build Report” inside the file to see the asset summary. Keep in mind that if you create multiple builds during one editor session you will have multiple build reports in your log. So only the last one is probably relevant.