In short, I am currently using a state machine to manage my player’s state, and I am trying to get my player to enter a “slow to stop” state when the input less than a magnitude of 0.2 (using the get_vector() function) and instead transition to a “sneaking” state when the magnitude is below 0.4 but above 0.2.
func process_input(event: InputEvent) -> State:
var input_dir = Input.get_vector("mov_left", "mov_right", "mov_up", "mov_down")
if (input_dir.x <= 0.2 and input_dir.x >= -0.2) and (input_dir.y <= 0.2 and input_dir.y >= -0.2):
return stop_state
if (input_dir.x <= 0.4 and input_dir.x >= -0.4) and (input_dir.y <= 0.4 and input_dir.y >= -0.4):
return sneak_state
return null
I basically want the skid to stop state to trigger if the stick stops receiving input or is quickly moved to the other side, to make a feeling of momentum, and the states themselves work very well, its just that sometimes the “sneaking” state will trigger first, so I would like it to only check for the “sneak” state input maybe every 3 or 4 frames so the program reliably detects a full stop or turn around. any suggestions>
You might consider keeping the previous input vector around and checking the difference in length; if the player is trying to go to sneak mode they’ll probably ease up on the stick, which would be a smaller length difference between updates, but if they’re trying to stop they’ll release the stick which will be larger differences.
I’d probably do input checking in _process() in order to get access to delta:
const SNEAK_THRESHHOLD = 0.25 # Wild guess, needs tuning.
var old_move_vec: Vector2 = Vector2.ZERO
func _process(delta: float) -> void:
[...]
old_move_vec = move_vec
var move_vec = Input.get_vector(...)
var mv_len = move_vec.length()
if mv_len < MV_DEADZONE: # stop.
if state != MoveState.stopped:
# trigger anything that happens on transition to stop
state = MoveState.stopped
elif mv_len < MV_SNEAK:
var len_diff = old_move_vec.length() - mv_len
if len_diff > (SNEAK_THRESHHOLD * delta): # Probably stopping.
if state != MoveState.walk:
state = MoveState.walk
else: # Small diff, probably trying to sneak.
if state != MoveState.sneak:
state = MoveState.sneak
[...]
This is just basic example; there are plenty of ways of refining this; you might want to consider, for example, if the stick deflection angle differs. As in, check the angle from Vector2.ZERO to each of the previous and current move vectors and see if the difference in angle is large. That might tell you (for example) that the player went from charging forward to trying to sneak back.
There are plenty of optimization opportunities as well, though it’s probably not worth optimizing something like this that happens at most once per frame.
Thanks, that should give me more than enough to work with, don’t know why I didn’t think of putting it in process, considering using _process was the solution to another issue I had with holding the stick sometimes not triggering the input event because the stopping state currently doesn’t take input, as I am trying to keep the code as simple and disconnected as I can at the moment.