|
Vulkan Schnee 0.0.1
High-performance rendering engine
|
This page shows a small custom actor with a custom logic component. The example is a basic enemy that owns health and destroys itself when health reaches zero.
Use this pattern for gameplay state that belongs on an actor but should stay separate from movement, rendering, or input code.
| Task | API |
|---|---|
| Actor base class | Engine::Entities::Actor |
| Logic component base class | Engine::Components::Logic |
| Attach component | Engine::Entities::Entity::addComponent<T>(args...) |
| Read attached component | Engine::Entities::Entity::getComponent<T>() |
| Spawn actor | Engine::Entities::Scene::spawnActor<T>(transform, args...) |
| Destroy actor | Engine::Entities::Scene::destroyActor(actor) |
HealthComponent stores health and invokes a death callback once when health reaches zero. It does not know about enemy behavior or actor destruction.
Logic requires the owning scene in its constructor. Actor-owned components can receive it automatically through Actor::addComponent<T>(args...) when their constructor supports Scene*.
IsUnique = true makes addComponent<HealthComponent>() return the existing health component if one is already attached.
Create the component in the actor constructor. Scene::spawnActor<T>() calls the actor constructor, adds the actor to the scene, then calls beginPlay().
Include the component header in the .cpp file before calling addComponent<HealthComponent>(). A forward declaration is enough in the actor header because the actor only stores a pointer.
The death callback owns the destruction policy. The health component only reports death.
Spawn the enemy from a scene with the same spawnActor<T>() call used by other actors.
spawnActor<T>() returns a raw actor pointer owned by the scene. Do not delete it directly. Use Scene::destroyActor() when gameplay should remove it.
Scene::destroyActor() queues destruction. Scene::flushPendingActorDestruction() later calls Scene::destroyActorImmediate(), which calls endPlay(), removes the actor from the scene, and deletes it. The engine flushes pending actor destruction after logic tick.
Keep damage entry points on the actor when other systems should not access components directly.
Direct component access is fine for small prototypes. Prefer an actor method when damage needs armor, hit reactions, score events, or team checks.
| Step | What Happens |
|---|---|
| spawnActor<T>() | Creates a SceneNode, constructs the actor, stores it in the scene, then calls beginPlay() |
| Actor constructor | Attach components and set callbacks |
| Actor::beginPlay() | Calls beginPlay() on all attached components |
| Actor::tick() | Ticks components with canTick() == true |
| Scene::destroyActor() | Queues the actor for destruction after logic tick |
| Scene::flushPendingActorDestruction() | Calls destroyActorImmediate() for queued actors |
| Scene::destroyActorImmediate() | Calls endPlay(), removes the actor from the scene, then deletes it |
Health does not need ticking. Add ticking only for components that update every frame.