Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

supporting mods (plugins, extensions) in Unity games

Discussion in 'Scripting' started by JoeStrout, Sep 16, 2014.

  1. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    We're starting to look into supporting mods in High Frontier. I've done my searching and found a few old threads (like this and this) about it, but nothing that seems very definitive (and often containing conflicting advice). We know it's possible because KSP has a very active mods community, and it's written in Unity. So, I'd like to sketch out an approach here and see if I'm missing anything.

    Goal: allow players to add new objects and functionality to the game, including new part/building types, and extensions to the simulation itself.

    Approach:
    1. Make object types data-driven as much as possible. Define robust files for defining object properties, and load models from some common format (perhaps using this OBJ importer). Have a "mods" folder in the game data, and scan that for new objects to load.
    2. Where custom code is needed, have modders compile a managed DLL in something like Xamarin Studio, and put that with the other data. Load this via System.Reflection.Assembly, and communicate with it via a defined API, as described here.
    I'll basically need to keep lists of these extra objects and invoke them periodically, or whenever an event happens, and then provide them entry points they can call back to make things happen in the game.

    So. Is this still the best approach? Are there any newer/better ways to load 3D models or code? Any gotchas we should watch out for?

    Thanks,
    - Joe
     
    shkar-noori likes this.
  2. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    That's basically what we do. We were using IronPython for "scripts" but the performance is terrible so we switched to making people compile a DLL.

    All of our data is XML driven whether it's modded or not so the same logical path is used for "real" data and mod data. Our caching system loads the game data before loading mod data and then simply overwrites game data with modded data based on pre-defined keys (usually some kind of "name" field).

    We'll probably end up using Assimp.Net to load models at run time - but we're undecided at this point. OBJ will work fine as long as nothing is animated.
     
    BmxGrilled likes this.
  3. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    I'm surprised nobody did a structure to save a GameObject hierarchy in a file that could be loaded at runtime without the need of Asset Bundles.
     
  4. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    We've abstracted away from that to the point where a modder doesn't need to know what a GameObject is nor care. They just write an XML file for a "unit" and they get a unit in the game. The only piece of Unity data that we serialize is Vector3 which we have a serializable wrapper around called Vec3String (it uses strings instead of floats because XmlSerializer will choke on floats with scientific notation). And we really only use that for our UI (yes, completely in XML as well) and maps published with our runtime editor.

    Actually - come to think of it - I don't know that we even use it in the UI :)
     
  5. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    *shiver*
     
  6. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Ah - you're one of *those* :)
     
  7. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    One of those what? One that prefer building a localization system and interface instead of handling annoying XML and hard-coding IDs?
     
  8. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    So am I — we'll be going with JSON instead, because we don't hate our users. ;) No, seriously though, thank you Kelso for sharing your solution. It sounds excellent.

    I hadn't heard of AssImp before (not crazy about the visual that name invokes, but I'm no better; I once made a Python drawing library with the acronym PIDDLE). Is this easy to use from Unity? I've found some threads here and there about it, but it looks pretty fiddly (especially on a Mac, I suspect).
     
  9. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    Not saying I don't but if you can find me a readable data format that handles complex/nested data types that can be written in a text editor then I'm all ears. It's a necessary trade-off if you don't develop and maintain your own solution for handling data.

    And I personally find JSON absolutely impossible to read :) Not to mention XmlSerializer is baked into the .NET framework so no need for an external library.
     
  10. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    One follow-up question, if you don't mind: did you consider using Mono.CSharp to dynamically compile and run C# code on the fly? This way modders wouldn't need Xamarin, but could just edit scripts with their favorite text editor.

    I know that wouldn't work on iOS, but on Mac/Win/Linux, it seems like it should work... unless there's some limitation on the version of Mono Unity uses. This is entirely possible, as I haven't tried it, and a few minutes of googling hasn't turned up much about it one way or the other.

    Just curious if you looked into that, and if so, why you chose to go with compiled DLLs instead.

    Thanks,
    - Joe
     
  11. LightStriker

    LightStriker

    Joined:
    Aug 3, 2013
    Posts:
    2,716
    You got me wrong... I'm into never reading a file, having a proper interface to expose relevant data.
     
  12. KelsoMRK

    KelsoMRK

    Joined:
    Jul 18, 2010
    Posts:
    5,539
    I didn't look into it but I would rather everything be compiled ahead of time instead of relying on the game to do it. From my past experience in making mods for RTS games I found it annoying the deeper I had to go into the game to figure out whether or not the "code" I had written worked. A DLL is at least compile-time safe without needing to touch the game at all.

    What you suggest is similar to what we did with IronPython and the level of abstraction is certainly nice for non-programmer types (or at least programmers who don't typically write strongly typed code) so I can see the upside if you can get it to work correctly. But I can tell you that the interface through which we create script instances via reflection is super nice and 100 times cleaner and faster than what we have for IronPython (we left it there in case we want to use it again at some point).
     
  13. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,840
    Fair enough. Thanks again!