playMaker

Author Topic: Movement Controller: Axis to Velocity 2D  (Read 2531 times)

Thore

  • Sr. Member
  • ****
  • Posts: 480
Movement Controller: Axis to Velocity 2D
« on: September 28, 2018, 08:53:00 PM »
I made two actions for myself, I thought I might as well share, too. There are also two test scenes to show you what's different to the other versions that exist.

What it does
Gets the axis, W/A/S/D, arrow keys, controller stick (as specified in Input Manager), and uses it to set velocity, with features you probably need, sending event based on direction, and more.

Use Case
The combination of getting the axis, storing various floats to then power animator and velocity was very common in my setups. But I wouldn't have done an extra action wasn't it for a specific problem I encountered. Because SetVelocity2D always sets some value (including zero), it interferes with physics. You won't notice this most of the time, unless the actor is for example attached to joints. You can account for this, by stacking together other actions and using multiple states, but this does it all in one block (normally the purpose of actions is to keep them modular, but this pack is just very common, why not put it together).



Hence I made actions that not only combine those steps, but also have a setting for a neutral deadzone.

AxisToVelocity2D & AxisRawToVelocity2D
These are two action twins that work similar, but differ only that one uses Input.GetAxis and the other Input.GetAxisRaw. Here are the settings, explained:

Game Object
Must be an object that has a rigidbody2d, that will be affected.

Axis Name
As you name it in the Input Settings (Edit > Project Settings > Input), and is typically named "Horizontal" or "Vertical".

Axis Orientation
Here you can set which velocity axis (Y/vertical or X/horizontal) you want to affect. This will typically match your axis name.

Store Axis Abs
This is a neat option to store the current axis value as an absolute, which you typically then feed to the animator (as set animator float), to drive the animations.

Multiplier
The build-in multiplier (as in GetAxis action) is used to amplify the axis value and is effecticely a kind of max speed value (e.g. the axis gives you +1, so with multiplier 5, the max velocity can be 5).

HasNeutral / Deadzone
When set, the neutral axis position will not update velocity, allowing it to be affected by physics objects, like free-wheeling. This interestingly also leads to a kind of momentum/inertia effect with the right rigidbody settings. See the effect in the scenes.

Both actions use an identical principle. Since the neutral axis position (i.e. stick in the middle) in the Raw version is 0, it's simply a bool with nothing to configure. The standard version has a smooth ramp, and here you can set which values are considered as a deadzone. It's simply mirrored (i.e. "0.5" goes from -0.5 to 0.5).

Event Button
When set, simply fires off an event (thus leaving the state) when the axis is either negative or positive (called Positive Button and Negative Button in the Input Settings). The usual purpose is to go into a different state to flip the sprite around.

Every Frame
What it says on the tin.


Updated:
Now also with world/local space. ;)
« Last Edit: September 29, 2018, 12:01:11 PM by Thore »

Thore

  • Sr. Member
  • ****
  • Posts: 480
Re: Movement Controller: Axis to Velocity 2D
« Reply #1 on: September 29, 2018, 01:22:43 PM »
I stress-tested this quite a bit, also with a fully fledged character, and seems to be even a tiny bit ahead of the conventional method.

Known Issue
I also found an issue: when you try hard enough changing direction (pressing A/D in quick succession, probably impossible with controller), you can create a situation where velocity is applied correctly, but an event was not fired. When you use events to flip the sprite, you can then have a situation where the state-change to flip didn't happen, i.e. the character walks backwards.

I think that comes from using Input.GetButtonDown(axis), which fires only when the axis goes into that direction, but does not constantly check in which position the axis is at the moment. So when it 'misses' that beat due to quick button presses (somehow), it won't self-correct. Another culprit could be FixedUpdate vs Update.

UPDATE
That seems to be it. I did check whether the axis was "pressed", too. Once I only check for axis, the issue is fixed.

Code: [Select]
// Event Switch


            if (Input.GetAxis(axisName.Value) > 0)
            {
                Fsm.Event(eventPositiveButton);

            }
            else if (Input.GetAxis(axisName.Value) < 0)
            {
                Fsm.Event(eventNegativeButton);

            }

            if (!everyFrame)
            {
                Finish();
            }

As usual, I post them here so you can play around, modify and test them. You're also welcome to try your hand :)

I see if other things come up, and then post the actual actions, without the scenes to test around.
« Last Edit: September 30, 2018, 09:40:55 AM by Thore »