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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

I'm not sure if I'm using interfaces correctly, and would like some clarification

Discussion in 'Scripting' started by jolechallinor3, Aug 18, 2022.

  1. jolechallinor3

    jolechallinor3

    Joined:
    Mar 6, 2019
    Posts:
    9
    So I've googled this and thought I was on the right track, but maybe not.

    I'm working on a small project involving enemies that can be taken over by the player, so the idea was to create enemies and player objects in a way that allows AI or player control to be interchanged.

    One thing I was working on is to create a script for an enemy, let's just call it enemycode, that also adds an enemybase script. The enemybase has the name of the enemy and the sprite, and other generic information. The actual enemy script has health and, what I was hoping to have, a serializable list of interfaces, which I now know doesn't work.

    The interface would be for ability classes, which has an ability method, cooldown, and a sprite for the ability on the GUI. My hope would be that most work could be done in the inspector, simply by adding the specific enemycode script, adding (for example) 4 ability slots in the inspector, dragging in the specific ability scripts made for that enemy, and then setting the cooldown and sprite. Later down the line would be specific AI and player controllers that could utilise these scripts to act as the specified enemy.

    Maybe I was overcomplicating it, but my idea here was to try and streamline the process a little, and allow for work to be done in the editor rather than entirely in code with huge enemy scripts full of abilities and junk.

    The process would go like this:
    Make an enemy object (an evil cube or something, in the editor), and add an enemy base script, which contains the name of the enemy, the sprite for use in the gui by the player, etc

    Add an enemycode script that actually contains everything the enemy does. It would have a serialised list of interfaces, where an ability script would inherit this interface and implement an ability cooldown, a sprite, a name, and an ability function.

    The user would drag all of these ability scripts into the list via the inspector, allowing the game to have access to them later for use by the enemy or the player.

    If I'm doing this wrong, can anyone help point me in the right direction, or maybe tell me what I can improve if my idea isn't entirely there?

    Thanks
     
    Last edited: Aug 18, 2022
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    Interfaces should be thought of as a contract. Anything that implements a particular interface agrees to the contract outlined by said interface.

    You can serialise non-Unity objects via interfaces by means of the SerializeReference attribute. You can also serialise polymorphic classes from a base class with it as well. However Unity doesn't have any built in inspector support for it.

    There are assets out there that do provide inspector work for this. Some paid, some free.

    If this isn't your kettle of fish, Scriptable Objects can also be used for this pluggable behaviour, though you'd need to use a base class rather than an interface.
     
  3. jolechallinor3

    jolechallinor3

    Joined:
    Mar 6, 2019
    Posts:
    9
    Thank you! Do you think I might be better off using Scriptable Objects instead? I'm not sure what would be the better use case here in all honesty. One other thing is that Scriptable Objects seem to imply they can't be changed at runtime, which may be an issue if I want to change any of the values, like decreasing the cooldown.

    This is good to know as well! I was under the impression it was just a "nope, can't be done" kind of thing
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    It's a case of a bit of this and a bit of that. Scriptable objects work out of the box, which is good. Downside is that you may have to make a whole ton and it becomes a bit of an organisational PITA.

    You can definitely mutate the data of scriptable objects through code, you just have to know that this data will persist between play sessions in the editor, so you sometimes end up having to do a lot of manual resetting through code.

    One work around is to wrap the data you need to mutate in a serialisable plain class that you hold in these SO's, and just copy that plain class at run time to avoid mutating the SO's data.

    So it's entirely doable you may just have to work around a few things.

    These days I just use SerializeReference and serialise this data straight into the assets that want this socketable behaviour. I use Odin Inspector to handle all the inspector stuff.
     
  5. jolechallinor3

    jolechallinor3

    Joined:
    Mar 6, 2019
    Posts:
    9
    It does seem like a lot of extra work, maybe an addon is the way to go if I can find one. I did look into Odin, but I'm not sure if I'll make use of all the features for it to be worth the price point.

    And regarding the extra work, do you think having different scripts for each ability is the way to go with this (assuming the interface method)? Or is it just going to add an extra form of mess with there being so many scripts?
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    Every project of every meaningful size is going to have a healthy number of scripts. More scripts shouldn't matter when your architecture is sound and your file organisation is robust (but also open to regular change).

    If anything lots of smaller, easy to maintain and understand scripts is easier to manage than fewer large scripts. I generally keep my projects broken down into many smaller scripts. I probably have over 300 script assets in my 'small prototype' I'm working on right now, not including my personal library of reusable tools.

    Also Odin has a trial on their website I believe. Worth doing some testing with it to see how it feels. I would definitely rate the addon 10/10. I'm also on the Odin Discord to lend a hand. ;p
     
  7. jolechallinor3

    jolechallinor3

    Joined:
    Mar 6, 2019
    Posts:
    9
    Thank you! Makes me feel a bit better about it.

    The whole idea with this project is to try something that would require the code to be a lot more modular and dynamic, and to see if I can try to make the entire process a lot more fluid to work with, especially inside the editor and the inspector (with adding the abilities and enemy details). These are things I normally struggle with. I think I'm on the way to solving that goal? It doesn't seem that bad I guess lol

    For now, this is what I'm gonna go with, since it seems to have what I need if I'm not misunderstanding it. I'll probably look into Odin when my financial situation improves a bit, since it does seem useful if I use everything or most things it has to offer.

    https://assetstore.unity.com/packages/tools/utilities/serialize-interfaces-187505#description
     
  8. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    6,008
    Striving to make modular and flexible code is a good thing in my books. Certainly something I strive for (I've only been coding a year and a half myself). Just also don't forget YAGNI...

    What you're aiming for is basically component/composition style architecture, which is more or less how Unity works at its core. And, as we know, Unity is quite the flexible game engine.