Vulkan Schnee 0.0.1 (22840dc8)
High-performance rendering engine
Loading...
Searching...
No Matches
Collision Responses

Collision responses define what happens when two collision profiles touch.

Use Block for physical contacts, Overlap for sensor contacts, and Ignore for pairs that should not interact.

APIs Used

Task API
Response enum Engine::Physics::CollisionResponse
Built-in profiles Engine::Physics::CollisionProfile
Register game profiles Engine::Physics::CollisionProfileRegistry::registerProfileEnum()
Load response table Engine::Physics::CollisionProfileRegistry::loadProfileResponses()
Set a collision profile Engine::Components::Collision::setCollisionProfile()
Set a profile by name Engine::Components::Collision::setCollisionProfileByName()
Body-level callbacks Engine::Components::PhysicsBody::onOverlapBegin() and Engine::Components::PhysicsBody::onCollisionBegin()
Shape-level callbacks Engine::Components::Collision::onOverlapBegin() and Engine::Components::Collision::onOverlapEnd()

Response Types

Response Physics solver Events Use case
Ignore No contact pair None Friendly-fire filtering, self collision filtering, disabled gameplay channels
Overlap No blocking response for pure sensor bodies Overlap begin, stay, and end Triggers, hand sensors, interaction volumes, area checks
Block Contact response Collision begin, stay, and end Floors, walls, props, projectiles that should hit solid objects

Ignore removes the pair from the active collision mask.

Overlap keeps contact detection so callbacks can run.

Block keeps contact detection and lets Bullet solve the contact.

Built-In Profiles

Profile name Default response
Engine.BlockAll Block
Engine.OverlapAll Overlap
Engine.IgnoreAll Ignore
Engine.WorldStatic Block
Engine.WorldDynamic Block
Engine.Pawn Block

Collision components that do not have a valid profile use the registry fallback profile.

The fallback is Engine.WorldStatic when that profile exists.

Pair Resolution

Each side of a pair declares a response to the other side's profile.

The engine resolves both responses into one final response.

Profile A says Profile B says Final response
Ignore Any response Ignore
Any response Ignore Ignore
Overlap Overlap Overlap
Overlap Block Overlap
Block Overlap Overlap
Block Block Block

Ignore wins over every other response.

Overlap wins over Block when neither side ignores.

Block only happens when both sides block.

Asymmetric Ignore rules are valid but usually indicate a configuration mistake.

The engine logs a warning when one side says Overlap or Block and the other side says Ignore.

Register Game Profiles

Game modules register their own profile enum during startup.

#pragma once
namespace AirHockey
{
enum class CollisionProfile
{
Hand,
Projectile,
ButtonTrigger
};
}
#include "AirHockey/CollisionProfiles.h"
#include "Engine/Physics/CollisionProfileRegistry.h"
void AirHockey::registerCollisionProfiles(
)
{
registry.registerProfileEnum<CollisionProfile>(
"AirHockey",
{
{ CollisionProfile::Hand, "Hand" },
{ CollisionProfile::Projectile, "Projectile" },
{ CollisionProfile::ButtonTrigger, "ButtonTrigger" },
}
);
registry.loadProfileResponses("assets/AirHockey/Data/config/collisionProfiles.json");
}
Registers collision profile names, enum mappings, and pair responses.
void registerProfileEnum(std::string domain, std::initializer_list< std::pair< ProfileEnum, std::string_view > > values)
Registers enum values as collision profiles under a domain prefix.
bool loadProfileResponses(const std::string &path)
Loads profile default and pair responses from a JSON file.

The profile names in JSON use Domain.Name.

AirHockey.Hand comes from the AirHockey domain and the Hand enum entry.

Configure Responses

Use defaultResponse for the profile's response to every profile not listed in responses.

Use responses for pair-specific overrides.

{
"profiles": {
"AirHockey.Hand": {
"defaultResponse": "Ignore",
"responses": {
"AirHockey.ButtonTrigger": "Overlap"
}
},
"AirHockey.Projectile": {
"defaultResponse": "Block",
"responses": {
"AirHockey.ButtonTrigger": "Ignore"
}
},
"AirHockey.ButtonTrigger": {
"defaultResponse": "Ignore",
"responses": {
"AirHockey.Hand": "Overlap"
}
}
}
}

This table gives these interactions:

Pair Final response Reason
AirHockey.Hand with AirHockey.ButtonTrigger Overlap Both sides explicitly overlap
AirHockey.Projectile with AirHockey.ButtonTrigger Ignore Projectile explicitly ignores the trigger
AirHockey.Hand with AirHockey.Projectile Ignore Hand default is ignore
AirHockey.Projectile with Engine.WorldStatic Block Projectile default is block and world static default is block

Keep trigger-style profiles overlap-only or ignore-only.

A body becomes a pure no-contact sensor when all of its collision profiles can never resolve to Block against any registered profile.

Set Profiles On Collision Components

Set the profile on the collision component, not on the physics body.

#include "AirHockey/CollisionProfiles.h"
#include "Engine/Component/Collision/BoxCollisionComponent.h"
#include "Engine/Component/PhysicsBodyComponent.h"
auto* body = addComponent<Engine::Components::PhysicsBody>();
body->setMass(0.0f);
body->setKinematic(true);
auto* trigger = addComponent<Engine::Components::BoxCollision>(glm::vec3{ 0.5f });
trigger->setCollisionProfile(AirHockey::CollisionProfile::ButtonTrigger);
trigger->setDebugName("ButtonTrigger");

Use names when the profile is data-driven or comes from an imported scene.

collision->setCollisionProfileByName("Engine.WorldStatic");

Multiple collision components can share one PhysicsBody.

Each collision component keeps its own profile and receives shape-level events for its own contacts.

Overlap Callbacks

Use overlap callbacks for sensors.

trigger->onOverlapBegin<HandActor>(
[this](HandActor& hand)
{
addOverlappingHand(&hand);
}
);
trigger->onOverlapEnd<HandActor>(
[this](HandActor& hand)
{
removeOverlappingHand(&hand);
}
);

Shape-level overlap callbacks filter by the other actor type.

They only invoke the callback when the other body belongs to that actor type.

Use body-level callbacks when you need the aggregate event and the set of collision components involved.

body->onOverlapBegin<ProfileTestActor>(
[](const Engine::Physics::CollisionEvent& event, ProfileTestActor& other)
{
for (Engine::Components::Collision* selfShape : event.selfComponents) {
inspectShape(selfShape);
}
}
);
Base class for collision shape components.
Actor-level collision or overlap event generated by PhysicsEngine.

CollisionEvent::response is Engine::Physics::CollisionResponse::Overlap for overlap events.

CollisionEvent::eventType is Begin, Stay, or End.

Block Callbacks

Use block callbacks for physical contacts.

body->onCollisionBegin<WallActor>(
[this](const Engine::Physics::CollisionEvent& event, WallActor& wall)
{
stopMovement();
}
);

Block contacts also run through the Bullet solver.

Use PhysicsBody::setMass(0.0f) or PhysicsBody::setStatic(true) for immovable world collision.

Use PhysicsBody::setKinematic(true) for objects moved by gameplay code.

Ignore Rules

Use Ignore when a pair should not generate solver contacts or callbacks.

Common cases:

Case Profile setup
Trigger ignores projectiles Trigger says Ignore to projectile or projectile says Ignore to trigger
Player ignores its own sensor volume Sensor profile says Ignore to pawn or pawn says Ignore to sensor
Area volume only detects hands Area volume defaults to Ignore and overrides hand to Overlap

Only one side needs to say Ignore.

Prefer symmetric configuration anyway, because it makes the table easier to read and avoids startup warnings.

Query Filters

Physics queries can use the same response table.

Engine::Physics::PhysicsQueryFilter contains a query profile and two booleans: includeOverlaps and includeBlocks.

filter.profile = registry->resolve(AirHockey::CollisionProfile::Projectile);
filter.includeOverlaps = false;
filter.includeBlocks = true;
CollisionProfileHandle resolve(ProfileEnum value) const
Resolves a registered enum value to its collision profile handle.
Collision profile filter used by PhysicsEngine scene queries.
bool includeOverlaps
Accept candidates that resolve to CollisionResponse::Overlap.
bool includeBlocks
Accept candidates that resolve to CollisionResponse::Block.
CollisionProfileHandle profile
Query profile tested against candidate body collision profiles.

The query checks the resolved response between the query profile and each collision profile on the hit body.

See Physics Queries for ray casts, sphere overlaps, and sphere sweeps.

Deprecated Trigger Flag

Engine::Components::Collision::setIsTrigger() still exists, but profile-based overlap is the supported path.

Use an overlap-only profile instead of setting trigger mode manually.

trigger->setCollisionProfile(AirHockey::CollisionProfile::ButtonTrigger);

Developer-Only Content