Scripting

Overview

SafiEngine uses native C++ behaviors for all gameplay logic. Behaviors are classes that extend the Behavior base class and have full access to every engine subsystem: input, physics, audio, ECS, rendering, and more.

Unlike external scripting languages, behaviors compile directly into the engine binary. This means zero overhead, full type safety, and complete access to the C++ standard library.

Behavior Lifecycle

Every behavior has two virtual methods:

class Behavior {
public:
  virtual void OnStart(flecs::entity e, Engine &engine) {}
  virtual void OnUpdate(flecs::entity e, Engine &engine, float dt) {}
};
MethodWhen CalledUse For
OnStartOnce, when play mode beginsInitialization, reading properties, caching references
OnUpdateEvery frame while playingInput handling, movement, game logic

Both methods receive the entity the behavior is attached to and a reference to the engine.

Engine Subsystems

Inside any behavior method you have access to every subsystem:

SubsystemAccessDescription
Inputengine.GetInput()Keyboard, mouse, action mapping
Physicsengine.GetPhysicsWorld()Velocity, gravity, collision bodies
Audioengine.GetAudioEngine()Sound playback, 3D spatialization
ECS Worldengine.GetWorld()Create/query/modify entities
Asset Managerengine.GetAssetManager()Load and cache assets
Debug Drawengine.GetDebugDraw()Wireframe lines, boxes, spheres
Event Busengine.GetEventBus()Publish and subscribe to events
Rendererengine.GetRenderer()View/projection matrices
Cameraengine.GetMainCamera()Get the active camera entity
Delta Timedt or engine.GetDeltaTime()Frame time in seconds

Workflow

  1. Create a .cpp file in Core/src/behaviors/
  2. Define a class extending Behavior
  3. Export a registration function
  4. Add the forward declaration and call in Behavior.cpp
  5. Add the file to Core/CMakeLists.txt
  6. Rebuild the engine

See Getting Started for a step-by-step walkthrough.

Section Contents