I’m working on an action game that has a focus on both combat and traversal. The player character has the ability to walk on walls, so I’m using a rigidbody since the built-in character controller can’t be rotated. Everything I’ve found online has said to handle moving the rigidbody in FixedUpdate and everything else in Update. However, I’m concerned that doing so will lead to situations where inputs are processed out of order, since the methods run at different intervals.
Currently my set-up is something like:
public class PlayerController : MonoBehaviour
{
Rigidbody controllerRigidbody;
InputAction jumpAction = InputSystem.actions.FindAction("Jump");
InputAction attackAction = InputSystem.actions.FindAction("Attack");
bool isAirborne;
bool jumpPressed;
public void Start ()
{
controllerRigidbody = GetComponent<Rigidbody>();
}
public void Update()
{
if (jumpAction.WasPressedThisFrame() == true)
{
jumpPressed = true;
}
if (attackAction.WasPressedThisFrame() == true)
{
if (isAirborne == false)
{
//Code for a ground attack
}
else
{
//Code for an air attack
}
}
}
public void FixedUpdate ()
{
if (jumpPressed == true && isAirborne == false)
{
controllerRigidbody.AddForce (9*transform.up, ForceMode.VelocityChange)
isAirborne = true;
jumpPressed = false;
}
}
}
A press of the Jump button would be processed in FixedUpdate since it adds a force to the rigidbody, whereas pressing the attack button doesn’t affect the rigidbody, so it would be processed in Update. However, if the game runs 60 FPS with FixedUpdate running at its default .02 second interval it could easily lead to cases in which the player presses Jump first then Attack, but Update runs before the next FixedUpdate causing the player character to attack first then jump.
There are two workarounds I can think of. One would be to handle everything in FixedUpdate. Something like:
public void Update()
{
if (jumpAction.WasPressedThisFrame() == true)
{
jumpPressed = true;
}
if (attackAction.WasPressedThisFrame() == true)
{
attackPressed = true;
}
}
public void FixedUpdate ()
{
if (jumpPressed == true && isAirborne == false)
{
controllerRigidbody.AddForce (9 * transform.up, ForceMode.VelocityChange)
isAirborne = true;
jumpPressed = false;
}
if (attackPressed == true)
{
if (isAirborne == false)
{
//Code for a ground attack
}
else
{
//Code for an air attack
}
attackPressed = false;
}
}
I’m worried though that this approach could throw-off the player’s timing, since the time between the game displaying a visual prompt and processing the input won’t always be the same.
The other idea is to handle the rigidbody’s movement by directly modifying its velocity in Update (multiplying by Time.deltaTime for continuous forces). Something like:
public void Update()
{
if (jumpAction.WasPressedThisFrame() == true)
{
jumpPressed = true;
}
if (attackAction.WasPressedThisFrame() == true)
{
attackPressed = true;
}
}
public voidUpdate ()
{
if if (jumpAction.WasPressedThisFrame() == true)
{
controllerRigidbody.linearVelocity += 9 * transform.up;
isAirborne = true;
jumpPressed = false;
}
if (attackAction.WasPressedThisFrame())
{
if (isAirborne == false)
{
//Code for a ground attack
}
else
{
//Code for an air attack
}
attackPressed = false;
}
}
I’m not clear what the consequences of doing this would be though (I’m only really using the rigidbody for handling collision, not for simulating realistic motion if that makes a difference).
If anyone could advise me on which approach to use, or if there’s another one I haven’t considered I would appreciate it.