Get a font from an assetbundle that is mebedded in dll?
Hi I am trying to read a font from a dll file and put it under resources folder in "editor". some one long ago suggested that We should use asset bundles for this. so, in unity 2017, i created an asset bundle from the font itself. the font was sitting in the root of Assets folder. when I look into the manifest I see that it says Assets/FontAwesome now, I embedded that asset bundle as binary in a dll project, this is the code I tried to use and get the font out of the bundle to write it in the folder :
byte[] bytes = typeof(FolderConstruction).Assembly.GetFromManifest("Buzz.Utils.Unity.Editor.Resources.fontawesome.bin");
var fontBundle = AssetBundle.LoadFromMemoryAsync(bytes);
var font = fontBundle.assetBundle.LoadAsset<Font>("FontAwesome.ttf");
var resource = AssetDatabase.LoadAssetAtPath<Font>(Resource.GLOBAL_RESOURCES_FOLDER + "/" + Resource.FONT_FOLDER_NAME + "/FontAwesome.ttf");
if (resource == null)
AssetDatabase.CreateAsset(font, Resource.GLOBAL_RESOURCES_FOLDER + "/" + Resource.FONT_FOLDER_NAME + "/FontAwesome.ttf");
AssetDatabase.Refresh();
When I run this code, I get these two errors : Failed to decompress data for the AssetBundle 'Memory'. System.NullReferenceException: Object reference not set to an instance of an object at Buzz.Utils.Unity.Editor.FolderConstruction..cctor () [0x00000] in :0 UnityEditor.EditorAssemblies:ProcessInitializeOnLoadAttributes()
the first byte[] returns correctly so I am sure I am reading the asset from the dll resources correctly, the problem sits after that, but i am not familiar enough with assetbundles to see what is wrong here.
please help
here is the manifest file of the bundle $$anonymous$$anifestFileVersion: 0 CRC: 3360611575 Hashes: AssetFileHash: serializedVersion: 2 Hash: e01f9c26e4f005e9b532977b626ae5fd TypeTreeHash: serializedVersion: 2 Hash: c1e9d3bf2af3e895c42799b814853128 HashAppended: 0 ClassTypes: - Class: 21 Script: {instanceID: 0} - Class: 28 Script: {instanceID: 0} - Class: 48 Script: {instanceID: 0} - Class: 128 Script: {instanceID: 0} Assets: - Assets/FontAwesome.ttf Dependencies: []
Answer by Jiraiyah · Sep 29, 2017 at 04:01 PM
Wow, Found the answer myself, can't believe it was simple, honestly, when you are dealing with editor stuff, why bother with asset bundles at all? here is the thing, first of all, still don't know why the code above does not work, so, if anyone knows how to read stuff from this sort of asset bundle, this answer is not the final solution for that question. now, as i said, when we are dealing with unity's editor stuff, we really don't need to bother with asset bundle at all ! so, what did I do? fist of all, import your font normally into "ANY" folder via unity's editor, because this way, unity will write some stuff on top of the file. then, in your dll project, add that file as a resource and mark it as embedded resource in the properties. time for the fun stuff, here is a simple yet useful extension method :
public static void ToDriveFromManifest(this Assembly assembly, string manifest, string path)
{
if (File.Exists(path))
File.Delete(path);
using (var stream = assembly.GetManifestResourceStream(manifest))
using (FileStream fileStream = new FileStream(path, FileMode.Create))
{
for (int i = 0; i < manifest.Length; i++)
fileStream.WriteByte((byte)stream.ReadByte());
fileStream.Close();
}
}
now, how do we use it? from the same project choose any of the classes you want, you can get the type of that class and from the type get your hand onto it's assembly and bam the rest is easy, read the stream manifest and use the extension method :
typeof(FolderConstruction).Assembly.ToDriveFromManifest("Buzz.Utils.Unity.Editor.Resources.FontAwesome.ttf", Resource.GLOBAL_FONT_AWESOME_DRIVE_PATH);
AssetDatabase.Refresh();
As you see in the above code, I just get the type of a class inside the dll project, calling appon it's type and get the assembly, the first parameter is your root namespace + Resources + the file "with" it's extension, this is the direct address to the file sitting in your dll's resources folder, the second parameter is the path on the hard drive that i want to put the font there, so, for example, if I want it under a company's name/Resources/Font, the path would be something like this :
public static string GLOBAL_FONT_AWESOME_DRIVE_PATH => Application.dataPath + "/" + COMPANY_NAME + "/" + RESOURCES_FOLDER_NAME + "/" + FONT_FOLDER_NAME + "/FontAwesome.ttf";
If you wonder about that => mark, it's a sugar code syntax in .net 3.5, normally if you use it in c# scripts, because it will be compiled by unity's compile it will yell at you, but in a dll project, you are free to use "Every" aspect of it because it will be compiled to IL by visual studio's compiler :D
as I said, this is a solution for the editor stuff, but still need for help in the case we embed an asset bundle, although, somehow i get the feeling that we can use the same extension method to extract the bundle on hard drive temporarily and then delete it when we are done, but still not sure how it would behave on something like mobile devices
Your answer
Follow this Question
Related Questions
Parse asset bundles to remap DLL calls in to sourcecode calls 0 Answers
Importing external DLLs to satisfy AssetBundle MonoBehaviour references 0 Answers
Serializable Class On ScriptableObject Null when loaded from AssetBundle 2 Answers
Problems with extracting dll files 0 Answers
Addressables LoadAssetAsync call errors with Object reference not set to an instance of an object 1 Answer