I’m working on an RPG style game and was wondering how I could implement RPG-like loot systems through scriptable objects.
Right now I have several weapons that are scriptable objects, for example, a Rusty Sword, an Iron Sword, and a Steel Sword. Each have their own damage values (e.g. 5, 10, 15). But I eventually want these to be dropped through code. So for example if you kill a monster, it might spawn one of these three. My initial thoughts would be to just create a GameObject with a script containing all possible loot drops with different percentages of dropping each one, then populating an array of ScriptableObjects that can be dropped. When the monster is killed, it will Instantiate a new “loot” gameobject containing one of the scriptable objects in the array, and when the player picks that item up, the loot gameobject is destroyed and the Scriptable Object it is holding is transferred over to the player’s inventory.
On top of this, I don’t want the values to be the exact same. So for example, a rusty sword might drop that does -50% to +50% more damage than a normal rusty sword, or any value in between. A rusty sword might drop that does 5 damage, or 2.5 damage, or 7.5 damage, or anywhere in between.
So yeah, those are my two main dilemmas: creating scriptable objects through code, and being able to modify values within a scriptable object as they are created. I wish I could provide some code, but honestly I am super new with scriptable objects and was hoping to get some feedback here. Right now all I have are some ideas on how I might implement these.
To create scriptable objects through code, you can use the ScriptableObject.CreateInstance() method to create a new instance of a scriptable object. For example, if you have a scriptable object class called Weapon, you could create a new instance of that class like this:
Weapon weapon = ScriptableObject.CreateInstance();
To set the values of the scriptable object, you can simply set the values of its properties. For example, if your Weapon class has a damage property, you could set its value like this:
weapon.damage = 10;
To randomly generate the values within a certain range, you could use the Random.Range() method to generate a random number within a specified range. For example, if you want to generate a random damage value between 5 and 15, you could use the following code:
float damage = Random.Range(5, 15);
Once you have created and initialized your scriptable object, you can add it to an array of scriptable objects that can be dropped by monsters. To do this, you would simply add the scriptable object to the array like this:
ScriptableObject loot = new ScriptableObject { weapon };
When a monster is killed, you can use the Instantiate() method to create a new game object that represents the loot. You can then set the scriptable object as the game object’s ScriptableObject component, like this:
GameObject lootObject = Instantiate(lootPrefab);
lootObject.GetComponent().scriptableObject = weapon;
When the player picks up the loot, you can transfer the scriptable object from the loot game object to the player’s inventory. To do this, you can get the ScriptableObject component from the loot game object and add it to the player’s inventory.
I hope this helps! Let me know if you have any other questions.