Hello. Suppose I have a ScriptableObject with a field that i want to be allowed to be set to null from the editor. Sure, I can use an array of size 1 at most or just remove it in awake, but having null in editor is so much nicer. Is there some magic annotation to allow it?
Not sure what you mean. The default value is null. Just don’t set it? And if you’ve set it but want it to be null, click it and press delete
I want to an option to remove the weapon and shield objects from this place in the editor.I want to an option to remove the weapon and shield objects from this place in the editor.
Ah, ok.
Perhaps you can structure your cards in a way that allows for this. Take the things that will be on all cards and put that in a base class, let’s call it CardBase. From there you can create a CombatCard that inherits from that card, and adds the Weapon and Shield. Now, if you want to have a card without those, create a base card. If you have a card with those, create a combat card.
// Just an example
public class BaseCard : ScriptableObject
{
[SerializeField] protected string _name;
[SerializeField] protected Sprite _image;
[SerializeField] protected string _description;
}
public class CombatCard : BaseCard
{
[SerializeField] protected Weapon _weapon;
[SerializeField] protected Shield _shiled;
}
If you want to let all cards have the option even if it won’t have the value set, there are no built-in ways of doing this that I am aware of, but there are options.
If you make your way over to here:
you will find a free tool that not only allows you to do this, but also a whole lot of other things. I used to use them before I got my hands on Odin, and I still use it sometimes when I do projects with people that do not have Odin.
In there you will find a ShowIf attribute. You can put a bool in your class like hasShield and let the ShowIf attribute show or hide the option based on the value.
This is the documentation for ShowIf
https://dbrizov.github.io/na-docs/attributes/meta_attributes/show_hide_if.html
It will be something like
[SerializeField] bool _hasShield;
[SerializeField, ShowIf(nameof(_hasShield))] Shield _shield;
Not exactly what I want. Usually chassis cards only have propulsion and space and energy cost. But some of them come with integrated weapon. And some with integrated shield. Or both. So inheritance will complicate things.
Weapons and shields are a bit special as not having the component is slightly different from having component with zero in all values.
I feel that having a null rather than a separate boolean is clearer because it is less redundant.
The object is just data and has no methods.
Actually, the object’s default would be null. The boolean is really just there to help the attribute determine if it should show or hide the field in the inspector. You can disregard it in the rest of the code and check the object for null. You can also use the OnValidate to clear it if it was set before.
private void OnValidate()
{
if (!hasShield) shield = default;
}
A different option - and the one I have used frequently - is to have those ‘components’ as separate scriptable objects. Then you can drag and drop them on the cards as needed and if it doesn’t need one, it will be null.