Search Unity

[Open Source] ModTool - Mod Support for Unity

Discussion in 'Assets and Asset Store' started by HelloMeow, Nov 21, 2016.

  1. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    This would happen with previous versions of ModTool sometimes. Some packages use Mono.Cecil, which ModTool also uses. This is fixed in version 2.0, because ModTool uses its own version of this library, with a different name.
     
  2. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Hi,

    I'm using ModTool v2 now. I passed a dll to the mod via the exporter and Visual Studio / Unity shows no errors when using functions from that dll.

    Letting prepare the mod, results in errors about those functions not being found, in the Log. The mod directory is created but the platforms folder inside are empty.

    Can I still utilise dlls? How? Or do I have to take a different route to pass a set of defined methods to a mod?

    Thank you for ModTool ! When it works, it is a huge comfort !
     
  3. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Yes, you should be able to include dll files by selecting them in the shared assets window. Can you share the error message?

    There are two ways of sharing code with mods. The easiest way is to use assembly definitions. If you select an assembly definition and select all associated script files in the shared assets window, the mod will be able to use those scripts.

    The second method of sharing code is by selecting precompiled dll files in the shared assets window.
     
  4. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Hi, here're the messages:

    upload_2022-6-25_20-40-27.png

    and EDITED: NOT ANYMORE attached is the Mod package and the project you can get from EDITED: DELETED it's a simple demo


    Edit: I already created the DLL and have it in use and would like to not move the code inside the main project.
     
    Last edited: Jun 26, 2022
  5. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Oh, and 1 idea: can you let compress the resulting exported files (I don't know if you alread do because the export fails) into 1 file and support loading from that 1 file from the defult Mods folder? Would make distribution and reception through users easier when they don't have to manage multiple files or decompress themself.
     
  6. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    The errors appear to be caused by Unity when building the asset bundles. I think it's a bug on Unity's side.

    The x86 platform of bUtilitiesDLL is unchecked, which I think is excluding it from compilation when building asset bundles. If you enable this, I think it should work.

    Also, AutoRunScript.cs is not associated with an assembly definition and will probably break any references when loading the mod.

    Currently mods are still folders. I do have a working version that uses a zip archive to package mods, but this adds a bunch of overhead. It's fine for small mods, but with larger mods the memory usage is significantly higher. Eventually I want to support both folders and zip archives.
     
    uani likes this.
  7. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    I thank you, the export succeeds. The code does not have effect yet though. Before I debug letting load and the code, do I have to target x86 when building? And IL2CPP is no hindrance? What do you mean by
    ? It is supposed to be unique to the mod, only calling used libraries like UnityEngine and my bUtilitiesDLL. I apologize for not digging deeper into assembly definitions, Unity's doc is too long and I didn't see relevant info on what "a d" do. Do I have to do something particular? What?
     
  8. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Ah, if it is supposed to be unique for each mod, you do not want to use assembly definitions. I never considered including a script like that. That's interesting.

    Unfortunately IL2CPP is not supported. This is because IL2CPP does not support loading .net code at runtime.
     
  9. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    :) :| :( ah, eh, ouh .. :) any idea of a possible outlook to achieve mod support with IL2CPP ?
     
  10. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    What if the mod code itself is all residing in a DLL and the main project know which entry point to call?
     
  11. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    It's not very likely. If you want to create assets and code in the editor and want to preserve references between the two, you need to use Mono. IL2CPP has too many limitations.

    There is a modding project (MelonLoader) that does have some IL2CPP support, but it still has some limitations. And I don't think it lets you use the Unity editor to create mods.
     
  12. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    1 other question:

    ModManager.ModRemoved does not incur a Mod.Unload() of the removed mod ? I would like a mod to remain loaded when the files are removed or are they not copied to RAM / main project runtime or can Unity load files from disk after it started? In that latter case and you do not let unload I guess I would have to let unload such a mod ?
     
  13. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    When a mod's files are changed or removed when the mod is loaded, it will remove or refresh the mod once it is unloaded. You should still be able to load scenes and assets from it while it is loaded.
     
    uani likes this.
  14. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    mod works in unity editor: my letting load and start code of my main project and the mod code itself works inside the game view of the main project in unity editor, unloading, reloading: everything works inside editor.
    But as a standalone Mono runtime the main project application discovers the mod but instructing to get it loaded and started has no effect.
    Ie. mod works with editor but not standalone. I haven't debugged standalone yet, i just finished all debugging and covering all possibilities and now would want to "ship" the moddable version of my application.
    Do you have an idea what is different between Editor and standalone and what I have to or can look out for?
     
  15. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    There shouldn't be any differences. If a mod doesn't load it might be invalid for some reason. You can check Mod.errors for any possible error messages. If there are none, you might find out more by checking the game's log file.
     
  16. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    fair enough, i'll see what i find there
     
  17. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    The issue is

    Code (CSharp):
    1. Fallback handler could not load library PROJECTNAME_Data/MonoBleedingEdge/data-000002581812F060.dll
    2. ReflectionTypeLoadException: Exception of type 'System.Reflection.ReflectionTypeLoadException' was thrown.
    3. Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies.
    4.   at (wrapper managed-to-native) System.Reflection.Assembly.GetTypes(System.Reflection.Assembly,bool)
    5.   at System.Reflection.Assembly.GetTypes () [0x00000] in <d744450a80a74703b521360ee53ddc26>:0
    6.   at ModTool.AssemblyResource.LoadAssemblies () [0x00111] in <0a017fac95174003bdffd47f7b8a08db>:0
    7. UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
    on mod.Load() (mod being a Mod).

    Note: A folder PROJECTNAME_Data/MonoBleedingEdge/ does not exist, it is either PROJECTNAME_Data/ or MonoBleedingEdge/.
    The netstandard.dll file is not in the generated output Managed folder. Copying it thither from the Unity Editor installation files does not help.


    And subsequently in the Loaded event handler:

    Code (CSharp):
    1. Shader 'Standard': fallback shader 'VertexLit' not found
    2. ReflectionTypeLoadException: Exception of type 'System.Reflection.ReflectionTypeLoadException' was thrown.
    3. Could not load type of field 'AutoRun:checker' (9) due to: Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies.
    4. Could not load file or assembly 'netstandard, Version=2.1.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies.
    5.   at (wrapper managed-to-native) System.Reflection.Assembly.GetTypes(System.Reflection.Assembly,bool)
    6.   at System.Reflection.Assembly.GetTypes () [0x00000] in <d744450a80a74703b521360ee53ddc26>:0
    7.   at ModTool.Mod.GetInstances[T] (System.Reflection.Assembly assembly, System.Object[] args) [0x00006] in <0a017fac95174003bdffd47f7b8a08db>:0
    8.   at ModTool.Mod.GetInstances[T] (System.Object[] args) [0x00020] in <0a017fac95174003bdffd47f7b8a08db>:0
    9. UnityEngine.DebugLogHandler:Internal_LogException(Exception, Object)
    and

    Code (CSharp):
    1. The script 'AutoRun' could not be instantiated!
    2. 0x00007ff92853ee8d (UnityPlayer) UnityMain
    3. 0x00007ff928543f13 (UnityPlayer) UnityMain
    4. 0x00007ff92852dd25 (UnityPlayer) UnityMain
    5. 0x00007ff928af976e (UnityPlayer) UnityMain
    6. 0x00007ff92839a92f (UnityPlayer)
    7. 0x00007ff92839a9ef (UnityPlayer)
    8. 0x00007ff928341753 (UnityPlayer)
    9. 0x00007ff92839ae6c (UnityPlayer)
    10. 0x00007ff92806881a (UnityPlayer)
    11. 0x00007ff9280674a1 (UnityPlayer)
    12. 0x00007ff92806707d (UnityPlayer)
    13. 0x00007ff928066af7 (UnityPlayer)
    14. 0x00007ff92806667b (UnityPlayer)
    15. 0x00007ff927de715d (UnityPlayer)
    16. 0x0000024f04ab16da (Mono JIT Code) (wrapper managed-to-native) UnityEngine.Object:Internal_CloneSingle (UnityEngine.Object)
    17. 0x0000024f04ab14d3 (Mono JIT Code) UnityEngine.Object:Instantiate<T_REF> (T_REF)
    18. 0x0000024f0bbb05bb (Mono JIT Code) bUtilities.MainScript:StartMod (ModTool.Mod)
    19. 0x0000024f0bbb0364 (Mono JIT Code) ModTool.ModManager:OnModLoaded (ModTool.Mod)
    20. 0x0000024f0bbacb34 (Mono JIT Code) ModTool.Resource`1<T_REF>:OnLoaded ()
    21. 0x0000024f0bb9cf06 (Mono JIT Code) ModTool.Resource/<Loading>d__28:MoveNext ()
    22. 0x0000024f04ac3320 (Mono JIT Code) UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
    where "AutoRun" is a script on the prefab I search for and let instantiate in my mod starting code.


    It is NOT fixed bei either Unity API Level .NET Standard 2.1 and .NET Framework, deleting all obj, Logs, Library folders and all VS files inside the project root, compressed standalone or uncompressed standalone output, presence of any .csproj files generated for every type.


    I use VS 2022 and Unity 2022.1.6f1
     
  18. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    I'm not sure what the issue is. I can load your mod fine, even on Android. Do you have any extra code that could reference netstandard? Do the game project and mod project have the same scripting backend?
     
  19. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    mod and main project were built with .NET Standard 2.1. That requires the host platform to provide its functionality. This can be circumvented by copying the netstandard.dll to the project program root folder. I tried various netstandard.dll : from dotnet, nuget, unity. The closest I got was that the dll was taken but required classes were not found inside.

    I switched the mod to .NET Framework API in Unity Editor Project Settings. NOW it works !

    :) Thank you !
     
  20. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Hello, you state "ModTool relies on AssetBundles, which means mods that are exported with a different version of Unity can have some issues." in the doc.

    Is the safest version of Unity the main project is build with the same version down to the 3rd version number the mod was created with? eg. 2022.1.7f1 or would 2022.1 suffice? Or does this depend on a package version (additionally) ?
     
  21. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    That's hard to say. In the last couple of years I haven't seen many issues when loading asset bundles from similar Unity versions. Issues used to be way more common.

    The exporter will only export mods with the exact same Unity version anyways. It checks the version and doesn't export if the version isn't the same. Do you think only showing a warning would be better?
     
  22. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Hi,

    hmm, regarding mod creation I think I consider requiring the exact version of Unity the modtool package is built with as acceptable (a warning I would prefer to pop up after modtool package import not when the mod creator wants to let export).

    When wanting to load a mod, can I, if i updated the main project Unity version since the mod was created, identify the Unity version of the mod first to possibly display a warning first or can i check for something not having loaded? I start the mod by running that "AutoRun.cs" functionality I created thus I coild skip starting mods which loaded with errors. You already provide an error output. I guess i would skip starting AutoRun for any error.
     
  23. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Yeah I think a warning after importing the exporter would make more sense. Especially because issues between Unity versions are much less common now.

    Before you load a mod, you can find the mod's Unity version in the mod's ModInfo.
     
  24. IlIlIlIlIlIlIlIlIlIlIlIlIl

    IlIlIlIlIlIlIlIlIlIlIlIlIl

    Joined:
    Jul 14, 2019
    Posts:
    2
    Code (CSharp):
    1. private void OnModLoaded(Mod mod)
    2.     {
    3.         Debug.Log("Loaded Mod: " + mod.name );
    4.  
    5.         AssetBundleRequest assetBundleRequest = mod.GetAssetsAsync<ScriptableObject>();
    6.         foreach (ScriptableObject item in assetBundleRequest.allAssets)
    7.         {
    8.             Debug.Log(item is BagItem);
    9.         }
    10.        
    11.     }
    Hello, I want to know how to read scriptableobject. When I want to convert scriptableobject to other classes, I cannot convert it.
     
  25. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    You're loading all ScriptableObjects, but you can load just the BagItems like this:

    Code (CSharp):
    1. AssetBundleRequest assetBundleRequest = mod.GetAssetsAsync<BagItem>();
    Then you have to cast them.

    Code (CSharp):
    1. foreach (var asset in assetBundleRequest.allAssets)
    2. {
    3.     BagItem item = asset as BagItem;
    4. }
     
  26. IlIlIlIlIlIlIlIlIlIlIlIlIl

    IlIlIlIlIlIlIlIlIlIlIlIlIl

    Joined:
    Jul 14, 2019
    Posts:
    2
    Code (CSharp):
    1. private void OnModLoaded(Mod mod)
    2.     {
    3.         Debug.Log("Loaded Mod: " + mod.name );
    4.  
    5.         AssetBundleRequest assetBundleRequest = mod.GetAssetsAsync<BagItem>();
    6.         Debug.Log(assetBundleRequest.allAssets.Length);
    7.         foreach (var Asset in assetBundleRequest.allAssets)
    8.         {
    9.             BagItem item = Asset as BagItem;
    10.             Debug.Log(item);
    11.         }
    12.  
    13.         foreach (var item in mod.assetPaths)
    14.         {
    15.             Debug.Log(item);
    16.         }
    17.  
    18.         AssetBundleRequest assetBundleRequest_1 = mod.GetAssetsAsync<ScriptableObject>();
    19.         foreach (var item in assetBundleRequest_1.allAssets)
    20.         {
    21.             Debug.Log(item);
    22.         }
    23.  
    24.     }
    When I load only the BagItem, I can't access it, but show that the file exists

    2022-08-25 105215.png
     
  27. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Your code works on my end. I can access my custom ScriptableObject assets like that. However, Mod.GetAssetsAsync is asynchronous. This means it loads the assets in the background and it might not finish loading them until a later point in time.

    In your case it might still be loading the assets when you try to access them. Does it work if you try Mod.GetAssets instead? If so, that is probably the issue.

    You can use AssetBundleRequest.completed or AssetBundleRequest.isDone to wait for it to complete.
     
  28. IceKontroI

    IceKontroI

    Joined:
    Jun 18, 2019
    Posts:
    8
    @HelloMeow This looks like a really powerful and useful tool. Is it possible to have an AddonMod depend on CoreMod, and then for AddonMod to able to change some aspect of CoreMod? Like swapping out a prefab's mesh, or editing some code in a prefab's script. That way, user downloads CoreMod + AddonMod, and we get the functionality of CoreMod, but with changes applied by AddonMod.
     
  29. IceKontroI

    IceKontroI

    Joined:
    Jun 18, 2019
    Posts:
    8
    To clarify, I'm wondering if a high level structure like this is possible with your tool:

    A mod can declare dependencies on any number of other mods. When a dependency is declared, all source files of that dependency become accessible to the mod. If the mod chooses to modify source files of one of its dependencies, let's say it changes logic in a C# script and changes the texture used in a Material, then its changed files get used instead of the original mod's.

    Of course, implementation of mod loading would have to account for the dependencies graph.
     
  30. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    That's not something ModTool can do currently.
     
  31. whitegreenstudios88

    whitegreenstudios88

    Joined:
    Dec 12, 2021
    Posts:
    10
    hi, is modtool 2.0 support webgl? tq
     
  32. uani

    uani

    Joined:
    Sep 6, 2013
    Posts:
    232
    Hello,
    I have another issue of the type https://forum.unity.com/threads/open-source-modtool-mod-support-for-unity.442185/page-3#post-8234055 but this time I haven't found a solution yet.

    The mod code

    Code (CSharp):
    1. placedVolcano = Instantiate(volcano, targetPlace, Quaternion.identity);
    results in the runtime log message

    Code (CSharp):
    1. Shader 'Standard': fallback shader 'VertexLit' not found
    2. MissingMethodException: Method not found: !!0 ModTool.ObjectManager.Instantiate<!0>(!!0,UnityEngine.Vector3,UnityEngine.Quaternion,string)
    3.   at UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) [0x00020] in C:\build\output\unity\unity\Runtime\Export\Scripting\Coroutines.cs:17
    4. UnityEngine.MonoBehaviour:StartCoroutineManaged2(MonoBehaviour, IEnumerator)
    5. UnityEngine.MonoBehaviour:StartCoroutine(IEnumerator) (at C:\build\output\unity\unity\Runtime\Export\Scripting\MonoBehaviour.bindings.cs:112)
    6. AutoRun:repeatableProcessCompleted(Int32)
    7. AutoRun:Start()
    8.  
    9. (Filename: C:/build/output/unity/unity/Runtime/Export/Scripting/Coroutines.cs Line: 17)
    and the mod is not discernible as being run.

    But inside Editor the mod runs and no messages are printed to the log.

    Even only instantiating and setting the position afterwards has the same result.

    Note: even an explicit "GameObject." prefix is no avail.


    Addendum:

    Using the Instantiate method I provide through my dll file from my main application works.
    The issue remaining is

    Code (CSharp):
    1. Fallback handler could not load library ..._Data/MonoBleedingEdge/data-000001E3639E99E0.dll
    2. Shader 'Standard': fallback shader 'VertexLit' not found
    and meshes from loaded mods are not lit by (realtime directional) light.
     
    Last edited: Apr 8, 2023
  33. foggedy

    foggedy

    Joined:
    Mar 19, 2024
    Posts:
    1
    Is there a way to unbuild my .mod file after it has been built?
    I need to recover my unity project Assets.
    It was a unityproject before and after i built it is an unusable .mod file which can only be read by the game and not edited by me anymore.
    When i click on the file it just open the windows movie player.
     
  34. jinnindo

    jinnindo

    Joined:
    Dec 8, 2015
    Posts:
    17
    Just to be clear, what defines what gets included in a mod export? (If this is already clearly explained, please link)
    Is it just everything that's in the project (excluding modtool folder itself) that meets the content setting (scenes/asset/code)?

    Related: so far, I can't make it export prefabs; the mods.prefabs is always empty with count of 0.

    Also, if it helps, it seems that when edit-project settings-editor-reload domain isn't toggled on, the mods in ModManager don't get reset and just pile up. I thought if Initialize was public, that could solve this, but I couldn't make it work, and there might be other problems with not reloading domain.

    Lastly, is there any connection between modtool 2.0 and umod 2.0?
     
  35. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Every scene, prefab and ScriptableObject asset that is not part of ModTool and is not a shared asset should be exported. If that's not the case, that's an issue I'd need to look at.

    I'm not sure about the reload domain thing. Could you give me more details?

    ModTool is not related to umod in any way, but it has similar features.
     
  36. rackneh2

    rackneh2

    Joined:
    Apr 12, 2020
    Posts:
    8
    Hey I'm using ModTool for a open-source port of MGS3, would it be possible to remove assets from the created mod file and add them back in before the mod is loaded?

    This would go for FBX files, textures, animation files and sound files, I assume it should be possible to make a modeditor that can open the assets modfile and take things out/put them in?

    This would allow me to easily share the core files and have people need a disc or the new steam release to get the assets
     
  37. HelloMeow

    HelloMeow

    Joined:
    May 11, 2014
    Posts:
    281
    Probably not. ModTool uses Unity's asset bundles for assets. If you can figure out a way to replace assets within asset bundles, then you could do it.