Camera collision / object avoidance

How can I prepare the standard camera before penetrating walls and objects? I don’t want to use the first person controller. I like like the mouse navigation.

Original Post on Discord

by user 684154017479524352

Hello there – we have an experimental AI bot :robot: that might be able to help you with your question. Would you like to try this out?

How it works:
Reply to the messages of the bot that end with a thread_id to interact with it and ask follow-up questions. You can also mention the bot directly in this channel to get help.

Help requested: please wait a moment…

Here is what I found for you :brain: Discord

Hello Matmat,

To prepare a standard camera that doesn’t penetrate walls and objects, while using mouse navigation, you can use a combination of the OrbitControls component for mouse navigation and raycasting to prevent the camera from moving through objects.

Here’s a step-by-step plan and code:

  1. Add OrbitControls to enable mouse navigation.
  2. Implement raycasting to detect when the camera is about to penetrate an object.
  3. If raycasting detects an object between the camera and its target, adjust the camera’s position.
import { Behaviour, OrbitControls, Raycaster, Vector3 } from "@needle-tools/engine";
import * as THREE from "three";

export class CustomCameraControls extends Behaviour {
    @serializable()
    private cameraDistanceMin: number = 1;
    @serializable()
    private cameraDistanceMax: number = 100;

    private orbitControls: OrbitControls;
    private raycaster: Raycaster = new THREE.Raycaster();
    
    awake() {
        this.orbitControls = this.gameObject.getOrAddComponent(OrbitControls);
        this.orbitControls.minDistance = this.cameraDistanceMin;
        this.orbitControls.maxDistance = this.cameraDistanceMax;
    }

    update() {
        this.preventCameraPenetration();
    }

    private preventCameraPenetration() {
        const camera = this.context.mainCamera;
        const targetPosition = this.orbitControls.target.clone();
        const direction = camera.position.clone().sub(targetPosition).normalize();
        this.raycaster.set(targetPosition, direction);

        const intersects = this.raycaster.intersectObjects(this.context.scene.children, true);
        if (intersects.length > 0) {
            const distance = intersects[0].distance;
            camera.position.copy(targetPosition).add(direction.multiplyScalar(Math.max(distance - 0.1, this.cameraDistanceMin)));
        }
    }
}

thread_P87FIiAgdve8MRf8opw8Joyf

Attach this script to your main camera. The awake method initializes the OrbitControls and sets the minimum and maximum distance from the camera to the target. The update method calls preventCameraPenetration each frame to check for objects between the camera and its target.

Please note that the code above assumes that no other object besides the camera will be within the minimum distance from the orbit control’s target. If you also have other dynamic objects around, you might need to customize your raycasting method to take them into account.

By using this script, you should be able to navigate with the mouse without the camera penetrating walls or objects. Remember that wall and object meshes need to have colliders for raycasting to detect them.

1 messages left GPT 4
thread_P87FIiAgdve8MRf8opw8Joyf
Thanks for your feedback!

Is what the bot suggested what you meant? You want a camera controller that effectively does collision avoidance?

The script doesn’t work yet. I can’t say if that’s what I need.

I don’t want my camera to penetrate walls and objects that are defined as coliders.

by user 684154017479524352

Have you tried just adding a spherecollider onto your camera?

a rigidbody set to no gravity + spherecollider works for me

20231222-190626_Collaborative_Sandbox_-_Google_Chrome-logo.mp4

at least if the velocity is not too high

I was thinking about rigid body… that’s exactly how I wanted it. Thanks for your quick support! Great, wish you and your families a happy holiday. See you soon and stay green. Mat

by user 684154017479524352

Changed the channel name: Camera collision / object avoidance