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\$

2 Answers 2

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\$
1
  • 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, 2015 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\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .