GhostWorld is a small, native, query-only physics world designed for deterministic raycast queries on an interpolated copy of your scene.
It is not a physics engine.
It does not simulate forces.
It exists purely to answer collision queries in a stable, predictable way.
This project was built primarily as a learning exercise in engine-style C++ and Unity native interop, and later evolved into a surprisingly useful tool.
- A separate “ghost” representation of your scene
- Runs alongside Unity, not inside its physics step
- Designed for raycast queries only
- Fully controlled by the caller
- Deterministic and allocation-free at runtime
Think of it as a shadow world used for queries, grounding, and collision checks where visual interpolation matters.
- ❌ A replacement for Unity Physics
- ❌ A rigidbody simulation
- ❌ A general-purpose physics library
- ❌ Automatically synchronized with Unity
- ❌ A full broadphase collision system
You explicitly decide:
- what colliders exist in GhostWorld
- when they are updated
- when queries are performed
GhostWorld currently supports:
- BoxCollider
- MeshCollider (triangle meshes)
Only raycast queries are supported.
No spherecasts, capsulecasts, overlap queries, or continuous collision detection.
GhostWorld is intentionally optimized for a small number of dynamic objects.
It does not implement a spatial broadphase beyond a simple AABB test.
There is no BVH, grid, sweep-and-prune, or tree structure.
Because of this:
- You should not register your entire static level
- You should not mirror all colliders from Unity
- You should only register dynamic or visually important objects
Typical use cases include:
- moving platforms
- elevators
- animated level elements
- dynamic props that affect grounding or visuals
These objects are usually few in number and benefit the most from interpolated queries.
GhostWorld is designed to be used alongside Unity Physics, not instead of it.
A recommended pattern is:
- Perform a raycast using Unity Physics
- Perform the same raycast against GhostWorld
- Discard or replace results based on your needs
This allows you to:
- keep Unity’s fast broadphase for static geometry
- use GhostWorld only where interpolation and visual correctness matter
- avoid duplicating large amounts of collision data
GhostWorld works best as a supplemental query layer.
GhostWorld consists of:
- a native C++ library
- a managed C# wrapper used from Unity
Initialization happens automatically at startup using:
RuntimeInitializeOnLoadMethod
You do not need to manually initialize the system.
At a high level, usage looks like this:
- Register dynamic colliders (BoxCollider or MeshCollider)
- Store the returned index
- Update collider transforms when they move
- Perform raycast queries (often in
LateUpdate) - Use results for grounding, visual effects, or animation logic
An example script demonstrating typical usage is provided in the Package folder.
- Meshes are assumed immutable after registration
- Collider indices are managed by the caller
- No automatic handling of destroyed or replaced colliders
- Queries must be performed on the main thread
- No broadphase beyond AABB testing
- Intended for small numbers of dynamic colliders
These constraints are intentional and keep the system simple and predictable.
GhostWorld exists to solve a specific class of problems:
- Visual interpolation vs physics timing mismatches
- Grounding jitter on moving platforms
- LateUpdate queries that must match rendered transforms
- Needing deterministic results for visual logic
If Unity’s physics already does what you need, you probably don’t need this.
A minimal example script is included in the Package folder showing:
- collider registration
- transform updates
- raycast queries
- result handling
That script is the best starting point.
GhostWorld is intentionally small, opinionated, and limited in scope.
It is meant to be:
- readable
- hackable
- educational
- practical for specific problems
Use it where it makes sense, and let Unity Physics handle the rest.
👻