- Home /
How to create an individual altered ScriptableObject?
I'm currently banging my head against a wall because I can't figure out how to do something that should be fairly simple. Basically, my game has a lot of items in it, and some of those items will be unique and be the only ones do a specific complicated series of tasks, I decided to make my items ScriptableObjects for the ease of implementing them through the inspector but I can't figure out how I can alter the method of a ScriptableObject instance without it altering everything else.
A very simplified example of what I have:
public class Item : ScriptableObject{
public string ItemName;
public virtual void Use(){
//Does generic item whatever that every item does.
}
}
.
public class HealingItem : Item{
public int AmountToHeal;
public override void Use(){
base.Use();
//Heal the player.
}
}
and there is one and only one item in the game that has a somewhat complicated usage where it heals you but it also heals slightly over your max health but only for a short time and it makes you invulnerable for a few seconds and a bunch of other stuff.
I could put this in the above HealingItem class and have a toggle to check if it's that one item, but it would be annoying and messy to have a hundred toggles for a hundred unique actions that only happen on unique individual items.
I could make another C# Script that extends HealingItem and has all the complicated stuff and then create an instance of that, but that would also be pretty messy as it means I need to create two files for every unique effect and it would quickly clog up the right click Create menu.
So, how can I do this? Or if I can't, what would be a better solution?
Answer by WarmedxMints · Sep 25, 2019 at 11:01 PM
I would probably do it a different way round. Have the item class and then add actions to it. That way you can have an object which just heals or one that heals and makes the player invincible and so on. You can have a list of item actions and iterate through them. That way, with a few actions, you can create many combinations.
public class Item : ScriptableObject
{
public List<ItemAction> Actions;
public string ItemName;
public void Use()
{
//Does generic item whatever that every item does.
var count = Actions.Count;
for(var i = 0; i < count; i++)
{
Actions[i].Use();
}
}
}
public abstract class ItemAction : ScriptableObject
{
public abstract void Use();
}
public class HealPlayer : ItemAction
{
public int HealAmount;
public override void Use()
{
//Heal Player
}
}
public class Invincibility : ItemAction
{
public int InvincibilityDuration;
public override void Use()
{
//Make Player Invincible
}
}
Answer by Mouton · Sep 26, 2019 at 08:29 AM
You could achieve the same as @WarmedxMints suggest with a unique Item
class and UnityEvents (https://docs.unity3d.com/ScriptReference/Events.UnityEvent.html).
Your Item
class defines a UnityEvent effects
field, then in the inspector you can define the different effects you require.
public class Item : ScriptableObject
{
public string ItemName;
public UnityEvent effects;
public virtual void Use(){
if (effects != null)
effects.Invoke();
}
}
You can use a static class ItemEffects
where all the applicable effects are stored,
public static class ItemEffects
{
public static Heal()
{
}
public static Poison()
{
}
}
If you need to pass arguments to your effects, you can use the generic version of Unity events (UnityEvent) and pass a struct/class.
public class Item : ScriptableObject
{
public string ItemName;
public UnityEvent<MyParams> effects;
public virtual void Use(MyParams params){
if (effects != null)
effects.Invoke(params);
}
}
Your answer
Follow this Question
Related Questions
Better way to reference Scriptable objects than using string? 1 Answer
Inventory and scriptable object items - please point me in the right direction 1 Answer
Instantiate a COMPLETELY Unique Instance of an Object 1 Answer
Accessing variable in a specific instance of a prefab 1 Answer
make a script unique to the gameobject it is attached to 2 Answers