Is it possible to create a second FixedUpdate function running at different rate?

Is it possible to create a second FixedUpdate function running at different step rate?

I have the need to run a block of code at a much faster rate than the physics require. Given that the code is used in a timing system I need very repeatable results from the time functions. Although I can run the fixed step at 0.001 and run the bulk of the code only on selected cycles the Unity physics is still being run at 1000 Hz.

I have considered using an Invoke style function but it does not have the accuracy required. Is there a way to run the fixed update rate at 500 Hz and use a delay function to call a block of code twice in one FixedUpdate call?

Yes, it’s possible to implement an independent FixedUpdate function. Keep in mind that “Fixed” doesn’t mean “fix-rate” or “constant-rate”. It means that it is “fixed” each Update. Here’s a sample class that implements a custom FixedUpdate (Updated version on github):

// C#
public class CustomFixedUpdate
{
    private float m_FixedDeltaTime;
    private float m_ReferenceTime = 0;
    private float m_FixedTime = 0;
    private float m_MaxAllowedTimestep = 0.3f;
    private System.Action m_FixedUpdate; 
    private System.Diagnostics.Stopwatch m_Timeout = new System.Diagnostics.Stopwatch();

    public CustomFixedUpdate(float aFixedDeltaTime, System.Action aFixecUpdateCallback)
    {
        m_FixedDeltaTime = aFixedDeltaTime;
        m_FixedUpdate = aFixecUpdateCallback;
    }

    public bool Update(float aDeltaTime)
    {
        m_Timeout.Reset();
        m_Timeout.Start();

        m_ReferenceTime += aDeltaTime;
        while (m_FixedTime < m_ReferenceTime)
        {
            m_FixedTime += m_FixedDeltaTime;
            if (m_FixedUpdate != null)
                m_FixedUpdate();
            if ((m_Timeout.ElapsedMilliseconds / 1000.0f) > m_MaxAllowedTimestep)
                return false;
        }
        return true;
    }

    public float FixedDeltaTime
    {
        get { return m_FixedDeltaTime; }
        set { m_FixedDeltaTime = value; }
    }
    public float MaxAllowedTimestep
    {
        get { return m_MaxAllowedTimestep; }
        set { m_MaxAllowedTimestep = value; }
    }
    public float ReferenceTime
    {
        get { return m_ReferenceTime; }
    }
    public float FixedTime
    {
        get { return m_FixedTime; }
    }
}

Instead of feeding deltatime you could also take out the internal reference time and feed in Time.time. However i think that way it’s more flexible :wink:

You can pass your desired timestep as well as a a delegate which will be called with the choosen rate.

Note: the MaxAllowedTimestep is very important. Without this check a heavy calculation inside your custom FixedUpdate function can almost freeze your game. That’s because when the claculation takes longer than the current deltaTime it will increase the next deltaTime which will result in even more calls of your CustomFixedUpdate function which results in a endless growing deltaTime and you get quickly tomillions of calls per Update. The MaxAllowedTimestep limits the execution of your delegate if it takes longer than this timespan.

Note: I’ve not tested the class ( i’ve just written it :wink: ), but it should work.

Use it like this:

// C#
public class SomeMonoBehaviour : MonoBehaviour
{
    private CustomFixedUpdate m_FixedUpdate;
    void Start()
    {
        m_FixedUpdate = new CustomFixedUpdate(0.001f, MyFixedUpdate);
    }
    void Update()
    {
        m_FixedUpdate.Update(Time.deltaTime);
    }
    void MyFixedUpdate()
    {
        // Do some fancy stuff every 0.001 seconds.
    }
}

This is exactly how Unity’s FixedUpdate function works. Inside MyFixedUpdate you might want to use:

  • m_FixedUpdate.FixedDeltaTime instead of Time.fixedDeltaTime (or Time.deltaTime)
  • m_FixedUpdate.FixedTime instead of Time.fixedTime

Just because it fits the topic: How FixedUpdate works :wink:

I’m not sure of the accuracy of this approach in small scale intervals, but try something along these lines:

    void Start()
    {
        StartCoroutine(MyUpdate());
    }

    IEnumerator MyUpdate()
    {
        while (true)
        {
            yield return new WaitForSeconds(1f / 1000f);

            // Do Stuff
        }
    }