- Home /
Scriptable Object won't Reset values after play.
I'm creating Pokemon-esk RPG game and decided to make the creatures scriptable objects.
Each object has the values of Name, Max Health, Current Health, and Attack List.
I've made it so a Slider acts as a health bar and lowers the Scriptable Objects "Current Health Integer". However after testing that out and stopping the program, the value in the Scriptable Object didn't change back to its original value.
Is there a way to prevent this?
Any changes made to scriptable objects during tuntime (in editor) stat changed on the object. How to handle this is to Instantiate an instance of the ScriptableObject, just like you'd instantiate anything else, except you don't need to define any position, rotation, or parenting, it simply instantiates an instance of the object into the RA$$anonymous$$.
Like this
public EnemyScriptableObject obj;
void Awake()
{
obj = Instantiate(obj);
}
Although it would be better to do something like this...
public class $$anonymous$$onsterData : ScriptableObject
{
[System.Serializable]
public class $$anonymous$$onsterDefinition
{
public string Name;
public int $$anonymous$$axHealth;
public Attack[] attacks;
}
public $$anonymous$$onsterObject prefab;
public $$anonymous$$onsterDefinition[] $$anonymous$$onsters;
public $$anonymous$$onsterObject Get$$anonymous$$onsterAtPosition(Vector3 position, int ID)
{
$$anonymous$$onsterObject mo = Instantiate(prefab, position, Quaternion.identity);
mo.Init($$anonymous$$onsters[ID]);
return mo;
}
}
public class $$anonymous$$onsterObject : $$anonymous$$onoBehaviour
{
public $$anonymous$$onsterDefinition definition;
private int currentHealth;
public void Init($$anonymous$$onsterDefinition md)
{
currentHealth = md.$$anonymous$$axHealth;
definition = md;
}
public void Heal(int amount)
{
currentHealth += amount;
if (currentHealth > definition.$$anonymous$$axHealth)
{
currentHealth = definition.$$anonymous$$axHealth;
}
}
public void PerformAttack(int attackID)
{
definition.attacks[attackID].Activate();
}
}
This approach isn't always available. It's ok when the GameObject with the reference to the SO "owns" the SO (for example if the SO is used to control that specific GameObject and/or other objects that need to reference the same SO can do so via that object), but it's no use when the SO is arbitrarily shared by objects.
For example, I use SOs for event systems, runtime data, and Finite State $$anonymous$$achines. In these systems, I need to be able to hook objects up to the same ScriptableObject in their inspectors. If each of these objects created their own local copy, they'd no longer be accessing the same data and nothing would work.
In situations like this, if I need to force the SO into a particular state at any time, then I'll just write code that explicitly puts it into that state. And usually also call the same code at the end to reset the data then (this avoids having spurious changes picked up by source control).
@RobAnthem So, if I understand the code correctly...
You're creating a public class in the $$anonymous$$onster's scriptable Object that contains the data for said $$anonymous$$onster. and the rest of the code is instantiating an a $$anonymous$$onsterObject with those stats?
And as for the $$anonymous$$onsterObject, it lists codes for changing health and attacking.
I tried to Copy Paste the code just to see what it would do, but I ran into a couple errors.
mo.Init($$anonymous$$onsters[ID]); gave me an error that said it couldn't convert $$anonymous$$onster.$$anonymous$$onsterDefinition to $$anonymous$$onsterDefinition.
Also, $$anonymous$$onsterDefinition in $$anonymous$$onsterObject could not be recognized.
I think I see where the code is going, but I'm still having difficulty implementing it.
Sorry my bad, any time you reference a subclass you have to call it from in the main class like this public $$anonymous$$onsterData.$$anonymous$$onsterDefinition definition
It's just one idea of how to handle this situation, mostly since you already defined your monsters into scriptable objects. $$anonymous$$y most recent enemy system is incredibly complicated and doesn't use scriptable objects, but ins$$anonymous$$d I have to setup prefabs of my enemies because they have so much to define about them. Enemy prefabs is a valid option as well, it would also be prudent to create a dynamic abilities/attacks system. Usually this is best done through a combination of animations, events, and a callback receiver that handles things. For example, my enemies have a number of attack combos and abilities and every time they are not currently attacking, being hit, or dead, they will randomly switch between attacks by changing an integer and passing the integer to the animator. The animator recieves it and when it moves to attack state it moves to the appropriate attack, then if the attack has effects like particles,, aoe's, etc. The animation calls to instantiate various effects as it progresses, and the callback script handles the input from the animation event. When my enemies have multiple abilities, I use my callback script to check which attack the enemy is currently using and assign that as my current ability, which contains effect info and prefab info for instantiation. This way, an enemy can have any number of attacks using the same ability system, and every ability be 100% different. I also use this exact same system for the player, because both my Enemies and Players inherit the same base interface which allows me to use Players and NPC's as though they were the same.
Thanks for the explanation. The prefabs idea might be preferable for me as a simpler solution.