lundi 23 février 2015

How to change AssemblyName after compilation to load as a mod in Unity3d

I have been investigating adding mod support to a Unity3D game. I am new to Unity (but not .NET), so if it seems like I am missing something obvious, please let me know because I probably am.


I would like to be able to export objects, including custom scripts, directly from the editor. It is easy enough to get the assembly associated with the script. Any loose scripts in the project seem to get compiled down to Assembly-CSharp.dll. The problem comes in when I try to load the assembly at runtime in another Unity project. Calling Assembly.Load(byte[]) returns to me the assembly of the current project, not the one represented by the byte array. I am assuming this is because the AssemblyName of the assembly from the mod project and the host project are both identical (Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null).


As a test, I updated my Visual Studio project for the mod project, renaming it from Assembly-CSharp to something different. This gets wiped out by Unity, but I can do a build before that happens and get the assembly I am looking for with a name other than Assembly-CSharp. Loading this via Assembly.Load(byte[]) seems to do the trick in a very simple 'import a script to rotate a cube' sort of scenario. While this appears to work, I am really looking for something more auto-magic single step from the Unity editor.


Now, on to the question...


If I understand the problem, what I am looking for is a programmatic way to change the AssemblyName of an assembly after compilation. All suggestions & advice welcome.


Some possible routes I have investigated and/or considered:


1) A magic API method to change AssemblyName and save it. This would be ideal, but I have yet to stumble across anything useful here.


2) Edit raw bytes of an assembly to change name? Not sure if this is possible, but if I could safely and reliably overwrite some of the raw bytes of an assembly to change its name, that would be swell.


3) Create a new dynamic assembly containing the types in the original assembly. My experience with dynamic assemblies is limited. I can create one, but what I am unsure how to do (if possible) is copy types defined in the original assembly to the new dynamic assembly.


4) Use the CSharpCodeProvider to manually compile the assembly. Assuming Unity supports it, then I assume this might work, seems like a pain though. I have not yet investigated what it would take to locate all scripts and references needed for compilation. I'd like to avoid it if possible.


5) Some magic with ilasm/ildasm. Assuming there is unity equivalents.. Is this something do-able with theses tools?


6) Programmatically update the csproj file and recompile. Seems pretty hacky and a pain. Guessing I would need to have code to support both Visual Studio and MonoDevelop.


I would prefer to avoid external tools and recompilation so one of the first 3 options would be ideal. Thoughts, ideas? Thanks!




Bonus Question: My 'import a script to rotate a cube' test seemed to work, however in the log during the loading of the assembly, I see the two messages below. That is not the assembly name I used, not sure where it came from. Should I be concerned? Is this going to come back to bite me later?



Non platform assembly: data-0B9D7940 (this message is harmless) Fallback handler could not load library C:/Dev/Test Projects/ModTest/Build/ModHost1/ModHost1_Data/Mono/data-0B9D7940.dll







Aucun commentaire:

Enregistrer un commentaire