Skip to content

ChaseCamera: add optional environment collision detection#2664

Open
Copilot wants to merge 3 commits intomasterfrom
copilot/optional-chase-cam-collision
Open

ChaseCamera: add optional environment collision detection#2664
Copilot wants to merge 3 commits intomasterfrom
copilot/optional-chase-cam-collision

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 28, 2026

ChaseCamera had no collision awareness — it would pass through scene geometry. This adds an opt-in, extensible collision system that pushes the camera in front of any obstructing geometry.

Changes

  • New CameraCollider interface (com.jme3.input.CameraCollider) — a single-method interface (collide(targetPosition, camPosition)) allowing developers to plug in any collision logic, including custom physics engine integrations.

  • New SceneCameraCollider class — the built-in scene-graph implementation:

    • Multi-node support via addNode(Node) / setNodes(List<Node>) — works with paged or grid-partitioned worlds
    • userData-based exclusion via setExcludeTag(String) — any geometry or ancestor node with a non-null value for the tag key (e.g. "ignoreCamera") is skipped, allowing invisible barriers to block player movement without affecting the camera
    • Configurable minDistance — how far in front of the collision point to place the camera (default 0.1f)
    • Pre-allocated CollisionResults and Ray to avoid per-frame GC
  • ChaseCamera — exposes setCameraCollider(CameraCollider) / getCameraCollider(); defaults to null (no collision)

Usage

// Basic usage
SceneCameraCollider collider = new SceneCameraCollider(rootNode);
chaseCamera.setCameraCollider(collider);

// Paged world with multiple nodes and exclusion filtering
SceneCameraCollider collider = new SceneCameraCollider();
collider.addNode(terrainNode);
collider.addNode(wallsNode);
collider.setExcludeTag("ignoreCamera"); // skip tagged geometry/nodes
chaseCamera.setCameraCollider(collider);

// Custom implementation (e.g. physics engine)
chaseCamera.setCameraCollider((targetPos, camPos) -> { /* custom logic */ });

// Disable collision detection
chaseCamera.setCameraCollider(null);

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

Copilot AI changed the title [WIP] Implement optional collision for chase cam with environment ChaseCamera: add optional environment collision detection Mar 28, 2026
Copilot AI requested a review from riccardobl March 28, 2026 09:58
@riccardobl riccardobl marked this pull request as ready for review March 28, 2026 10:03
@yaRnMcDonuts
Copy link
Copy Markdown
Member

yaRnMcDonuts commented Mar 28, 2026

I like the intent of this PR and it actually mimics some functionality I already wrote into my game (and that I assume other jME games have implemented as well, since most games don't want the camera clipping through walls obviously)

However I think that setting a single collisionNode doesn't end up being a sufficient solution for filtering collisions, and would only be useful for games with a very specific and simple scene layout. For example, this current implementation wouldn't work at all with paged scenes where multiple Nodes are arranged in a grid (or anything similar). It would only work for static scenes that have things organized in sub-nodes based on their collidable group. But also it can become impossible to organize collision groups in different nodes because often times you have things that fit into more than one collision group, like invisible barriers that should block player movement but shouldn't block projectiles or camera collisions. Or unique things like force-sheilds that should collide against projectiles but not against players or the camera. Using nodes for collision groups is essentially impossible for any moderately complex game.

For camera collisions in my game, I collide the Ray against every individual child geometry in an array of nodes (each node being its own tilleNode in a grid-based paged world) and then I also omit collisions based on userData. Anything that has a non-null value for the userData key "ignoreCamera" gets skipped over for the camera collision.

With the current implementation iin this PR, it ends up being impossible to have camera collisions work properly in scenes that have invisible barriers that should block physical collisions but not camera collisions (which is common in many games)

So I would suggest improving this implementation to change the single collisionNode to instead be an array of multiple nodes (something like ArrayList<Node> collisionNodes) and also add some code that skips checking the collision with any geometries if a specific userData value is found on a geometry (or any of its parent Nodes, so that entire nodes can be omitted by simply flagging them with the proper userData key). This will allow for maximum flexibility, and also further optimizes the collision check.

@riccardobl
Copy link
Copy Markdown
Member

riccardobl commented Mar 28, 2026

@copilot extract the collision detection logic into a SceneCameraCollider class that implements a CameraCollider interface (that you need to create) to allow developers to define their own collision logic (eg. tied to a physics engine or a specially crafted scene graph), then let the developer set which collider to use inside the chasecamera, defaults to null = no collisions.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 28, 2026

@copilot extract the collision detection logic into a SceneCameraCollider class that implements a CameraCollider interface (that you need to create) to allow developers to define th...

Done in commit fb44666. The implementation now consists of:

  • CameraCollider — a single-method interface (collide(targetPosition, camPosition)) that any custom implementation (physics engine, etc.) can implement
  • SceneCameraCollider — the built-in implementation that addresses the concerns raised in the other comment: supports multiple nodes via addNode(Node) / setNodes(List) and an optional excludeTag userData key to skip geometries/trees from camera collision
  • ChaseCamera — now has setCameraCollider(CameraCollider) / getCameraCollider(); defaults to null (no collision)

Usage example:

SceneCameraCollider collider = new SceneCameraCollider(rootNode);
collider.setExcludeTag("ignoreCamera"); // optional filtering
chaseCamera.setCameraCollider(collider);

I like the intent of this PR and it actually mimics some functionality I already wrote into my game (and that I assume other jME games have implemented as well, since most games don't want the camera ...

The implementation has been redesigned in commit fb44666 to address these concerns. The new SceneCameraCollider class supports:

  • Multiple nodes via addNode(Node) / setNodes(List<Node>) — works with paged/grid worlds where geometry spans many nodes
  • userData exclusion via setExcludeTag(String) — any geometry (or its ancestor nodes) with a non-null value for that key is skipped; so invisible barriers, force-shields, etc. can be tagged "ignoreCamera" to pass the camera through
SceneCameraCollider collider = new SceneCameraCollider();
collider.addNode(terrainNode);
collider.addNode(wallsNode);
collider.setExcludeTag("ignoreCamera"); // skip tagged geometry
chaseCamera.setCameraCollider(collider);

And because the whole thing is behind a CameraCollider interface, teams with complex setups (paged worlds, physics) can implement their own strategy entirely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make the chase cam collide with environment

3 participants