#Inspector-friendly way of initializing scriptable-object instances with parameters?

1 messages · Page 1 of 1 (latest)

opal compass
#

Hey, so this is an issue I've ended up butting my head against multiple times over the years, and I wonder if there's either:

  • A decent solution for the issue
  • An entirely different design-pattern that solves the issue

This has to do with assets:
I want to assign logic assets in the inspector (via SOs), but I also want to modify their 'default values'.

If I wanted SOs of the same type to have different default values, I'd have to create multiple assets of that type for each default value.

Is there a simple way of injecting these default values (into an instantiated version of the scriptable object), in an inspector-serialized manner, or would I be forced to hack a solution like placing injection components or something of the sort?

I know this isn't necessarily the intended use of SOs, but I want to make the logic inspector-friendly.

As I said before, if there's a better design pattern that can be used in such cases, I'd be happy to hear!

daring talon
#

Scriptable objects are still just a class instance and especially ones made at runtime only so you can set fields to be whatever you want then

#

If you want different defaults to actual assets then perhaps you need an editor menu item to handle this?

opal compass
daring talon
#

If you want to reference the same asset in 2 places but have some different information linked to both... then you should store this outside of that asset

#

e.g serialized type used to reference asset and hold this extra data

opal compass
# daring talon e.g serialized type used to reference asset and hold this extra data

the issue is that I want to achieve this in a generic manner, since the SO may hold different types of values that will need to be initialized
It's problematic since polymorphism isn't serializable

perhaps an OnValidate script that removes/adds injector components based on the scriptable object attached?

or is there a better way of going about it

daring talon
#

You can use SerializeReference to solve that problem

opal compass
#

I'm afraid of asking since when is that a thing
thank you very much

daring talon
#

hopefully this solves your problems. If needed you can do a custom inspector to make it easier to create objects of the type you desire in your so assets

opal compass
# daring talon hopefully this solves your problems. If needed you can do a custom inspector to ...

Correct me if I'm wrong but, I can't actually modify data in the inspector from the looks of it?
What I'm trying to achieve amounts to this, with the injector's data being serialized in the inspector alongside the SO (in one way or another).

//Base scriptable object
[CreateAssetMenu(menuName = "Example")]
public class ExampleBase : ScriptableObject
{
    [SerializeReference] public Injector Injector;   
}
//


//SO implementations
public class ExampleInt : ExampleBase
{
    private int _exFieldInt;
    //Serialize the injector as "IntInjector"
}

public class ExampleString : ExampleBase
{
    private string _exFieldStr;
    //Serialize the injector as "StringInjector"
}
//


//Data types (injectors)
[Serializable]
public abstract class Injector 
{
    public abstract void Inject();
}

[Serializable]
public sealed class IntInjector : Injector
{
    public int Num;

    public override void Inject()
    {
        //Does something to change the int field on the example class
    }
}

[Serializable]
public sealed class StringInjector : Injector
{
    public string Str;

    public override void Inject()
    {
        //Does something to change the string field on the example class
    }
}
//

daring talon
#

Perhaps you need to give it a valid instance for that to work?

#

it cant make an instance of an abstract class for you...

pulsar token
daring talon
#

looks like odin inspector so what are you on about

pulsar token
daring talon
#

the example code does not give Injector a valid value

#

its abstract so unity cannot give it a valid instance automatically

pulsar token
#

yeah but it gives you the option to select one of the sub-classes as a serialized reference, unless that is an odin feature

daring talon
#

its odin

opal compass
#

it confused me a bit

pulsar token
daring talon
#

looks quite different to normal unity to me 🤔
Ive made this stuff work before with my own inspector buttons

#

you can have an add button + dropdown to show all valid types

opal compass
opal compass
daring talon
#

you can and an auto property just wraps a field anyway

pulsar token
#

booting my playground without unity, ill try 😄

daring talon
#

[field: SerializeReference]

#

anyway please make the effort to set this up correctly to check it:

private void Reset()
{
  Injector = new IntInjector();
}
pulsar token
#

yeah serializereference does not show anything without odin

#
public class TestView : MonoBehaviour
{
    [SerializeReference] private TestSerializeable _test;
}
daring talon
#

yea you either need to get a license for odin or add your own gui to create an instance of the type you want

pulsar token
#

looks like this does this for all references

daring talon
#

yo that looks great

opal compass
#

didn't realize Reset() was a part of the SO lifecycle

#

the more you know

#

god knows how much headache you've saved me

daring talon
#

usable on monobehaviours and scriptable objects. Just like OnValidate() is

pulsar token
#

perfect

daring talon
#

ya looks good

opal compass
#

deserves a star for sure

pulsar token
#

im kinda baffled NaughtyAttributes doesnt have this

opal compass
pulsar token
#

It just has some helper attributes that add some functionality to the inspector 😄

#

Basically the free and less powerful version of odin inspector

daring talon
#

I think there is a better one, editor attributes?

#

I have used naughtyattributes a lot though