Tick Rate and Time Deltas

Different Update Rates for Game Objects

Is it possible to have different objects in the game world update at different rates?

Abstract art representing computer programming

Yes, it's absolutely possible to have different objects in the game world update at different rates. This technique can be useful for optimizing performance, creating interesting gameplay effects, or simulating systems with different time scales. Let's explore how we can implement this:

Using Timers for Different Update Rates

One approach is to use timers for each object or group of objects that need to update at a different rate. Here's an example:

#include <SDL.h>
#include <iostream>
#include <memory>
#include <vector>

class GameObject {
public:
  virtual void update(float dt) = 0;
  virtual ~GameObject() = default;
};

class FastObject : public GameObject {
public:
  void update(float dt) override {
    // Update logic for fast objects
    std::cout << "Fast object updated\n";
  }
};

class SlowObject : public GameObject {
public:
  void update(float dt) override {
    // Update logic for slow objects
    std::cout << "Slow object updated\n";
  }
};

class World {
private:
  std::vector<std::unique_ptr<
    GameObject>> objects;
  float fastUpdateTimer = 0.0f;
  float slowUpdateTimer = 0.0f;

  // 20 times per second
  const float FAST_UPDATE_INTERVAL = 0.05f;
  // 2 times per second
  const float SLOW_UPDATE_INTERVAL = 0.5f;

public:
  void addObject(
    std::unique_ptr<GameObject> obj) {
    objects.push_back(std::move(obj));
  }

  void update(float dt) {
    fastUpdateTimer += dt;
    slowUpdateTimer += dt;

    if (fastUpdateTimer >=
      FAST_UPDATE_INTERVAL) {
      for (auto& obj : objects) {
        if (dynamic_cast<FastObject*>(obj.
          get())) {
          obj->update(fastUpdateTimer);
        }
      }
      fastUpdateTimer = 0.0f;
    }

    if (slowUpdateTimer >=
      SLOW_UPDATE_INTERVAL) {
      for (auto& obj : objects) {
        if (dynamic_cast<SlowObject*>(obj.
          get())) {
          obj->update(slowUpdateTimer);
        }
      }
      slowUpdateTimer = 0.0f;
    }
  }
};

int main(int argc, char** argv) {
  SDL_Init(SDL_INIT_VIDEO);
  World gameWorld;
  gameWorld.addObject(
    std::make_unique<FastObject>());
  gameWorld.addObject(
    std::make_unique<SlowObject>());

  Uint64 previousTime = SDL_GetTicks64();
  while (true) {
    Uint64 currentTime = SDL_GetTicks64();
    float dt = (currentTime - previousTime) /
      1000.0f;
    previousTime = currentTime;

    gameWorld.update(dt);

    SDL_Delay(16); // Roughly 60 FPS
  }

  SDL_Quit();
  return 0;
}
Fast object updated
Fast object updated
Fast object updated
Fast object updated
Slow object updated
Fast object updated
Fast object updated
...

In this example, FastObject instances update 20 times per second, while SlowObject instances update only 2 times per second.

Using Update Counters

Another approach is to use update counters for each object:

class GameObject {
protected:
  int updateFrequency;
  int updateCounter = 0;

public:
  GameObject(int freq) : updateFrequency(freq) {
  }

  virtual void update(float dt) {
    updateCounter++;
    if (updateCounter >= updateFrequency) {
      updateCounter = 0;
      performUpdate(dt * updateFrequency);
    }
  }

  virtual void performUpdate(float dt) = 0;
};

class FastObject : public GameObject {
public:
  // Update every frame
  FastObject() : GameObject(1) {}

  void performUpdate(float dt) override {
    // Fast update logic here
  }
};

class SlowObject : public GameObject {
public:
  // Update every 10 frames
  SlowObject() : GameObject(10) {}

  void performUpdate(float dt) override {
    // Slow update logic here
  }
};

This approach allows for more flexibility in setting update frequencies and doesn't require separate timers for each update rate.

Considerations

When implementing different update rates, keep these points in mind:

  1. Consistency: Ensure that the behavior of objects is consistent regardless of their update rate.
  2. Interpolation: For visual smoothness, you might need to interpolate between updates for slow-updating objects.
  3. Physics: Be cautious when applying different update rates to physics objects, as it can lead to inconsistencies or instabilities.
  4. Performance: While this can optimize performance, be mindful of the overhead introduced by the system itself.

By implementing different update rates for game objects, you can create more efficient and dynamic game worlds, tailoring the update frequency to the needs of each object or system in your game.

This Question is from the Lesson:

Tick Rate and Time Deltas

Learn how to create smooth, time-aware game loops that behave consistently across different hardware configurations

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

Tick Rate and Time Deltas

Learn how to create smooth, time-aware game loops that behave consistently across different hardware configurations

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 67 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved