1
\$\begingroup\$

I'm currently building a small game, and I've created this simple character controller using FixedUpdate, which executes every frame.

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    /// <summary>
    /// Check for a key press, and if that key is pressed,
    /// move in a specified direction if there are no obstacles.
    /// </summary>
    private void MovePlayerOnKey(KeyCode keyCode, Vector3 direction)
    {
        Collider[] hitColliders = Physics.OverlapSphere(this.transform.position + direction, 0.1f);
        if(Input.GetKey(keyCode) && hitColliders.Length <= 0)
        {
            this.transform.position += direction;
        }
    }

    /// <summary>
    /// FixedUpdate is used to ensure that the player is
    /// moving in sync with the step of the Physics engine,
    /// and not executing a variable amount each frame.
    /// </summary>
    public void FixedUpdate()
    {
        this.MovePlayerOnKey(KeyCode.W, new Vector3(0, 1f, 0));
        this.MovePlayerOnKey(KeyCode.A, new Vector3(-1f, 0, 0));
        this.MovePlayerOnKey(KeyCode.S, new Vector3(0, -1f, 0));
        this.MovePlayerOnKey(KeyCode.D, new Vector3(1f, 0, 0));
    }
}

While the code itself works, the player moves much too fast for my liking, and I can't change the step of the player either, it has to stay at 1 in order for other game mechanics to function properly.

The only solution I can think of is changing how FixedUpdate runs by running it less often. Is it possible to make FixedUpdate run once every n frames?

\$\endgroup\$
1
\$\begingroup\$

Well, it seems like this was an easy solution. Thanks to a suggestion by @Quill, I added this to the top of my class:

public int timeStepIncrement = 1;
public int timeStepDivisor = 5;
private int timeStepCounter;

I then changed FixedUpdate to look something like this:

public void FixedUpdate()
{
    if(this.timeStepCounter <= 50000 - this.timeStepIncrement)
    { this.timeStepCounter += this.timeStepIncrement; }
    else
    { this.timeStepCounter = 0; }

    if(this.timeStepCounter % timeStepDivisor == 0)
    {
        this.MovePlayerOnKey(KeyCode.W, new Vector3(0, 1f, 0));
        this.MovePlayerOnKey(KeyCode.A, new Vector3(-1f, 0, 0));
        this.MovePlayerOnKey(KeyCode.S, new Vector3(0, -1f, 0));
        this.MovePlayerOnKey(KeyCode.D, new Vector3(1f, 0, 0));
    }
}

Now it only executes once every five frames, and is very configurable.

\$\endgroup\$
  • 2
    \$\begingroup\$ Instead of this.timeStepCounter % timeStepDivisor == 0 You should use if(this.timeStepCounter > timeStepDivisor) { timeStepCounter -= timeStepDivisor; }. After some time the integer would overflow and it could produce unexpected results. \$\endgroup\$ – wondra Sep 7 '15 at 17:36
0
\$\begingroup\$

You can change the fixed time step in the time settings of your project, but it may look a bit laggy if you turn it up too much.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.