Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
Tick System

The tick system executes game logic every frame. Classes receive time delta values and can implement update logic, movement, input handling, etc.

Architecture

The engine runs ticks in this order each frame:

  1. GameModule::preTick()
  2. All ITickable::preTick() (entities with Ecs::Tick component)
  3. GameModule::tick(deltaTime)
  4. All ITickable::tick(deltaTime) (entities with Ecs::Tick component)
  5. GameModule::postTick()
  6. All ITickable::postTick() (entities with Ecs::Tick component)

ITickable Interface

Classes that implement the tick interface inherit from EngineCore::ITickable.

File: Engine/include/Engine/Core/Tick.h

Methods

virtual void preTick();
virtual void tick(double deltaTimeSeconds);
virtual void postTick();

All methods have empty default implementations. Override only what you need.

Example: Actor with Tick

class MyActor : public EngineCore::Actor {
public:
void tick(double deltaTime) override {
Actor::tick(deltaTime); // Call parent first
// Your logic here
position += velocity * deltaTime;
}
};
An Actor is similar to an EngineCore::Entity. An actor is an Entity with a transform.
Definition Actor.h:24
void tick(double deltaTime) override
Executed every frame.
Definition Actor.cpp:28

Entity and Actor already inherit from ITickable. Override tick() directly.

Enabling Tick

Entities don't tick by default. You must enable ticking.

For Entity/Actor

class MyActor : public EngineCore::Actor {
public:
MyActor(std::shared_ptr<SceneNode> node, Scene* scene)
: Actor(node, scene) {
enableTick(true);
}
void tick(double deltaTime) override {
Actor::tick(deltaTime);
// Update logic
}
};
void enableTick(bool enable)
Enables or disables ticking for this entity.
Definition Entity.cpp:18

What enableTick Does

Adds an Ecs::Tick component to the entity's EnTT registry entry:

void Entity::enableTick(bool enable) {
auto& registry = Ecs::RegistryManager::get();
if (enable) {
registry.emplace<Ecs::Tick>(data, this);
} else {
registry.remove<Ecs::Tick>(data);
}
}
static entt::registry & get()
Gets the registry for all components.
Tag for everything which wants to receive tick events.
Definition EcsData.h:146

The engine queries all entities with Ecs::Tick each frame and calls their tick methods.

LogicComponent Tick

LogicComponent doesn't inherit from ITickable but has its own tick system.

Enabling Component Tick

class MyComponent : public EngineCore::LogicComponent {
public:
MyComponent(Scene* scene) : LogicComponent(scene) {
setCanTick(true); // Enable ticking
}
void tick(double deltaTime) override {
// Component logic
}
};
Base class for all logic components that can be attached to an actor. Provides access to the scene,...
void setCanTick(bool enable)
Enables or disables ticking for this component.
virtual void tick(double deltaTime)
Called every frame if ticking is enabled.

How It Works

Actor::tick() iterates through components and calls tick() on those with ticking enabled:

void Actor::tick(double deltaTime) {
Entity::tick(deltaTime);
for (auto& component : components) {
if (component->canTick()) {
component->tick(deltaTime);
}
}
}

Non-ITickable Classes

For classes that don't inherit from ITickable, wrap them or call their update methods manually.

Option 1: Manual Calls in Actor

class ThirdPartySystem {
public:
void update(float dt) { /* ... */ }
};
class MyActor : public EngineCore::Actor {
ThirdPartySystem system_;
public:
void tick(double deltaTime) override {
Actor::tick(deltaTime);
system_.update(static_cast<float>(deltaTime));
}
};

Option 2: Wrap in LogicComponent

class ThirdPartySystem {
public:
void update(float dt) { /* ... */ }
};
class ThirdPartySystemComponent : public EngineCore::LogicComponent {
ThirdPartySystem system_;
public:
ThirdPartySystemComponent(Scene* scene) : LogicComponent(scene) {
setCanTick(true);
}
void tick(double deltaTime) override {
system_.update(static_cast<float>(deltaTime));
}
};
// Usage in actor
actor->addComponent<ThirdPartySystemComponent>(scene);

Option 3: Ticker Class (Unused)

The codebase includes EngineCore::Ticker but it's not connected to the main loop. The tick() method is empty. Use the EnTT-based system instead.

GameModule Tick

Override GameModule methods for global game logic.

File: Engine/include/Engine/Game/GameModule.h

class MyGame : public EngineCore::GameModule {
public:
void preTick() override {
// Runs before all entities
}
void tick(float deltaTime) override {
// Update global state
gameTime_ += deltaTime;
}
void postTick() override {
// Cleanup after all entities
}
};
virtual void preTick()
virtual void tick(float deltaTime)
virtual void postTick()

Async Tick (Asset Pipelines)

Asset pipelines use tick() for state machine advancement, not frame timing.

Example: Ecs::ModelAssetPipeline::tick(bool async)

void tick(bool async = true) {
submitLoadModel(async);
processModel(async);
processMaterial(async);
processMeshData(async);
}

These ticks happen each frame but advance background loading tasks. The async parameter controls whether work happens on background threads or the main thread.

Delta Time

Delta time is the seconds elapsed since the last frame.

Get delta time:

double dt = EngineManager::getInstance().getEngineModule()->getDeltaTimeSeconds();

Typical usage:

void tick(double deltaTime) {
// Move 5 units per second
position += direction * 5.0f * static_cast<float>(deltaTime);
// Rotate 90 degrees per second
rotation += 90.0f * static_cast<float>(deltaTime);
}

Checking Tick State

// Entity
if (entity->canTick()) { /* ... */ }
if (entity->canEverTick()) { /* ... */ }
// LogicComponent
if (component->canTick()) { /* ... */ }

Summary

Class Type Inherits ITickable? How to Enable Tick Method
Entity/Actor Yes enableTick(true) Override tick()
LogicComponent No setCanTick(true) Override tick()
GameModule No Always ticks Override tick()
Scene Yes N/A (not used for logic) N/A
Other classes No Wrap in component or call manually N/A

Execution order: GameModule → Entities (with Ecs::Tick) → Components (within their entity)

Files: