- Home /
How to check if an enum’s case has changed
I am using an enum with several cases, controlled by a switch statement. Inside of Update(), I have a function running that checks the case of the enum. Therefore, I have scripts being executed every frame that relate to the current case of the enum. This doesn’t seem to be a problem, but I am running into a challenge with calculations that depend on the enum’s case.
I have a calculation that I want to run ONLY WHEN the enum’s case switches from one to another, not every frame. For example, let’s say if the enum case is “A” I want to subtract 2 from some equation in another script, while if it’s “B” I want to subtract 1 from that equation. Currently, the script is subtracting 1 every frame of the game, instead of just once. I think you see the problem here.
So I have two questions:
Is there a magic line of code that references when an enum’s case has changed from one thing to the next? My first stab at solving this problem was to create an Event, and at its heart this requires some code like if (enum’s case has changed) {Do this;}
Is there a better way to do what I’m trying to do? Is the solution to remove the script in Update() that checks the case of the enum every frame? I’m sure that what I’m trying to do has been done before, so maybe someone out there knows a better way.
For a general analogy, let’s say the player’s movement state is an enum with 3 cases: walk, crouch, prone. When it’s state is "walk", I want the player's movement speed to be multiplied by 1, "crouch" should be movement speed multiplied by 0.5, and "prone" is speed multiplied by 0.2. How would you code that so you aren’t continuously multiplying the movement speed every frame of gameplay, only upon changing from walking to crouching?
Thank you!
Answer by dpoly · Jun 17, 2017 at 02:02 PM
First terminology: enum is a type; an enum does not have a case, but a variable of some enum type has a value. You are asking how to write code that only executes when a variable changes value.
There are dozens of ways to do this very common thing, but the easiest by far looks like this.
// declare variable to hold old value
MoveKind oldmove;
void Update() {
// do this only if the value changed
if (move != oldmove) {
// do stuff
oldmove = move;
}
}
Answer by ShadyProductions · Jun 17, 2017 at 12:46 PM
You can add a bool value like:
bool alreadyDone = false;
and from the moment your enum is hit, check if your alreadyDone is false then do your logic and set alreadyDone to true;
That way it will only happen once and not repeat again.
Answer by XeniaPhe · Dec 06, 2021 at 11:46 PM
I know it's probably too late but what you need is a property along with the backing field which you probably already have:
[SerializeField] float walkSpeed=1f;
[SerializeField] float crouchSpeed=0.5f;
[SerializeField] float proneSpeed=0.2f;
float currentSpeed=1f;
MovementState _currentState;
public MovementState CurrentState
{
get => _currentState;
set
{
_currentState=value;
OnStateChanged(value);
}
}
private void OnStateValueChanged(MovementState state)
{
switch(state)
{
case Walking:
currentSpeed=walkSpeed;
break;
case Crouching:
currentSpeed=crouchSpeed;
break;
case Proning:
currentSpeed=proneSpeed;
break;
}
}
But the problem with this is,there is nothing preventing you from using the field itself instead of the property which will then obviously not function as intended,it's ok to use the backing field for getting purposes though.