5

Im trying to create a button and multiple Sliders that update based each others values. Since every button and set of sliders is highly related I tried to call one method that would update the set, therefore I call one Update method for GenerateItem, rather than calling Update on each Object and making them reference each other.

Why am I getting the error above, and what is the "Unity" way to solve this? My program will likely have a lot of these sliders and Buttons so I would rather not code them all by hand.

GenerateItem must be instantiated using the ScriptableObject.CreateInstance method instead of new GenerateItem

void Start () {

    Button a = ((GameObject)Instantiate(prefabButton)).GetComponent<Button>();
    Slider b = ((GameObject)Instantiate(prefabCreationSlider)).GetComponent<Slider>();
    Slider c = ((GameObject)Instantiate(prefabCapacitySlider)).GetComponent<Slider>();
    Text d = ((GameObject)Instantiate(prefabText)).GetComponent<Text>();
    items.Add(new GenerateItem("OxyGen", 0.5f, 50f,a,c,b,d));
}

// Update is called once per frame
void Update () {
    items.ForEach(a => a.BtnUpdate());
}

I tried:

GenerateItem o= ScriptableObject.CreateInstance(GenerateItem);

but couldn't figure out how to set the properties of the object.

1 Answer 1

7

I don't see the code of the ScriptableObjects.

But you either have to use CreateInstance(Type) which returns a ScriptableObject and cast the created instance to your type:

GenerateItem o = (GenerateItem) ScriptableObject.CreateInstance(typeof(GenerateItem));

Or simply use the typed version ScriptableObject.CreateInstance<Type>() which returns a Type and therefore doesn't require the typecast (I prefer this one)

GenerateItem o = ScriptableObject.CreateInstance<GenerateItem>();

Than you can set the properties as usual

 o.<some property> = <some value>;

Note that the properties/fields ofcourse have to be public for this solution.


Alternatively have some kind of

public void SetValues(string name, float value1, float value2, Button button, Slider slider1, Slider slider2, Text text)
{
    // Apply values

    <some property> = <some value>
    /* ... */
}

method inside of the ScriptableObjects so you can simply call

o.SetValues("OxyGen", 0.5f, 50f, a, c, b, d);

Another alternative (and I personaly like this one most) - Factory pattern

Only allow setting of the values on instantiation and protect them against later direct changes. Have a method in GenerationItem that takes completely care of the instantiation and setting the values

public static GenerateItem CreateInstance(string name, float value1, float value2, Button button, Slider slider1, Slider slider2, Text text)
{
    // Let the method itself take care of the Instantiated
    // You don't need "ScriptableObject." since this class inherits from it
    GenerateItem o = CreateInstance<GenerateItem>();

    // Then directly set the values
    o.<some property> = <some value>;

    /* .... */

    return o;
}

So later in your class you just have to call

var o = GenerateItem.CreateInstance("OxyGen", 0.5f, 50f, a, c, b, d);

This makes sure values cannot be changed afterwards that easy. Depends on your needs.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for the help! Note: There is a small typo, "Instace" is missing an "n" in "GenerateItem o = ScriptableObject.CreateInstace<GenerateItem>();" I copied it directly, so ran into the minute error.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.