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

Question Scriptable object with added scripts

Discussion in 'General Discussion' started by Hedenrag, Mar 10, 2023.

  1. Hedenrag

    Hedenrag

    Joined:
    Mar 8, 2022
    Posts:
    5
    Im making a game where you have units who can use different weapons which you can equip and those weapons have some stats. those stats are stored in scriptable objects but i also wanted to store special abilities which should be scripts.
    The scriptable object would look something like this:
    Code (CSharp):
    1. [CreateAssetMenu(fileName = "Weapon", menuName = "ScriptableObjects/Weapons", order = 1)]
    2. public class Weapon : ScriptableObject
    3. {
    4.     public string weaponName;
    5.     public int damage;
    6.     public int critChance;
    7.     public int maxDurability;
    8.     public int buyCost;
    9.     public int sellCost;
    10.  
    11.     public PassiveAbility passive;
    12.     public AttackAbility attack;
    13. }
    14.  
    15. [Serializable]
    16. public class PassiveAbility
    17. {
    18.     public virtual void PassiveUse(CombatStatus status)
    19.     {
    20.         Debug.Log("passive ability used");
    21.     }
    22. }
    23.  
    24. [Serializable]
    25. public class AttackAbility
    26. {
    27.     public virtual void AttackUse(CombatStatus status)
    28.     {
    29.         Debug.Log("attack ability used");
    30.     }
    31. }
    The problem is that it does not show any box to drag the script to. I tried inheriting from object and then it shows the box but i cannot drag it into. The main reason im using scriptable objects is because its not the final class but an itermediate.
    The final class looks something like this:
    Code (CSharp):
    1. public class UsedWeapon : MonoBehaviour
    2. {
    3.     Weapon weapon;
    4.  
    5.     public int currentDirability;
    6.  
    7.     public int damageUpgrades;
    8.  
    9.     public Effect addedEffect;
    10. }
    Having the inherited abilities like this would help a lot since the abilities are shared between multiple objects for example a priest dagger and a priest wand will both have as passive that it heals you over time although they are different types of weapon.

    I will add more addons for weapon modifications but until i do not solve this problem it doesn't make much sense to coninue.
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,881
    You want to use [SerializeReference], which allows for polymorphic serialisation of plain C# reference types via a base class or interface type.

    Problem is Unity doesn't have built in support for it, so you'll need to make or find some editor tools that allow you to use it.
     
  3. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    Your ability classes can inherit from IAbility interface and Weapon class can have a reference of IAbility like this:

    [SerializeReference, SerializeReferenceButton] IAbility ability;

    Then in the inspector you will have the list of all classes(that must not derive from UnityEngine.Object type) that implement the interface 'IAbility'. You just have to pick your desired implementation from the editor.

    'SerializeReferenceButton' is an attribute developed by TextusGames and I added this along with a list of useful attributes from NaughtyAttribute just here. Make sure to follow the install instructions in the github page.
     
    Last edited: Mar 12, 2023
    Hedenrag and DragonCoder like this.
  4. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,322
    Your "weapon" field in UsedWeapon is private. Private fields are hidden from inspector by default. To serialize private fields, add
    [SerializeField]
    attribute before them. This will make inspector field appear.

    He does not need those, his classes are not polymorphic. Interfaces also are not necessary.
     
  5. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,881
    They've defined virtual methods, I assume, with the intent derive from their types and override said methods.

    Nonetheless it's hard to overstate how much flexibility you get with
    [SerializeReference]
    .
     
  6. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,322
  7. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,881
    What...

    You really should read the documentation better:
    upload_2023-3-11_20-43-28.png

    SerializeReference is for non-Unity object reference types. I know what it can and can't do, I use it every day mate.
     
    neginfinity likes this.
  8. neginfinity

    neginfinity

    Joined:
    Jan 27, 2013
    Posts:
    13,322
    Alright, my mistake.

    Still, see this part:
    There are also gotchas at the end.

    SerializeField is enough, and while there are virtual methods, OP is not using polymorphism.
     
  9. Hedenrag

    Hedenrag

    Joined:
    Mar 8, 2022
    Posts:
    5
    Thanks, this was exactly what i needed. This was a bit tricky to set up for versions prior to 2021.3 since the struct named build target does not exist and unity uses different versions of c# so i needed to change variable names and comment a couple things, otherwise it works perfectly for this usecase.

    If some newcommer comes here looking for the easy solution here is how:

    Go to your project folder /packages and open the file manifest.json add:

    "com.kaiyum.attributeext2": "https://github.com/kaiyumcg/NaughtyAttributes.git",
    "com.kaiyum.editorutil": "https://github.com/kaiyumcg/EditorUtil.git",

    inside dependencies
    go back to unity and wait to recompile.
    If you use a version prior to 2021.3 you will get errors, otherwise you will be ready to go

    To solve these you have to go to
    Library\PackageCache\com.kaiyum.editorutil@54e46ba7be\Editor\KaiRepoUtil.cs

    and comment lines 37, 40, 41, 44, 54.
    i didnt completely understand what those lines did but it seems those solved the errors.

    if your c# implementation does not allow use of same name variables for diferent scopes level you will get other errors. I think this gets fixed with Unity 2020.1 but im not sure.
    to fix it you need to enter
    Library\PackageCache\com.kaiyum.editorutil@54e46ba7be\Editor\Ext\GetCompEx

    and change the name of some variables to fix name collisions.

    This is what worked for me, hope it helps anyone else.
     
    kaiyum likes this.
  10. Hedenrag

    Hedenrag

    Joined:
    Mar 8, 2022
    Posts:
    5
    Yes, i forgot to add the public / [SerializeField] but that was a uninportant mistake of my problem I only showed that part of the code to show my final expected use so if anyone had a workaround that would work could tell me. But thanks anyway for telling me.


    I thought so too but i coudnt find anywhere someone who didnt ended up using Interfaces and Inheritance which wold be a pain to set up for a large amount of types working with inheritance. @kaiyum had the correct answer.
     
  11. kaiyum

    kaiyum

    Joined:
    Nov 25, 2012
    Posts:
    686
    I should have said few stuffs about it, sorry for that.
    • All my repos in github are meant to be used in 2021.3+ in favor of C# 9.0
    • AttributeExt2 has dependency of 'EditorUtil'. Since unity can not handle git dependencies(yet), you have manually add the line in manifest.json, as stated in github page readme
    • 'KaiRepoUtil' ensures certain scripting define symbols in your current platform's player setting, depending upon what libraries/frameworks(from me or from unity or from other wellknown sources) are being used in your project. It is used so that I can enable or disable certain features automatically depending upon a set of other features. For example, enable certain camera optimization if URP is present.
    • Ext folder in 'EditorUtil' are meant for a set of repos of mine that can use them in editor.
    • If you wish to avoid all these, you can just get the serialize reference button attribute from original textusgame thread. :) Though, you will miss a tons of useful attributes in such case. :(