Raycast Detection
In this document, we will discuss how to use raycast and line stripe cast to detect colliders in physics world.
Raycast Detection
Raycast detection is a intersection determination of one ray and another shape, as shown in the figure below.
Construct Rays
A ray consists of a starting point and a direction. There are several more common ways to construct a ray, as follows:
via the constructor of start + direction, ray or the static interface
create
.tsimport { geometry } from 'cc'; // Construct a ray starting from (0, -1, 0) and pointing to the Y-axis // the first three arguments are the starting point, the last three arguments are the direction const outRay = new geometry.Ray(0, -1, 0, 0, 0, 1, 0); // or by static method 'create' const outRay2 = geometry.Ray.create(0, -1, 0, 0, 0, 1, 0);
via the static interface
fromPoints
of start point + another point on ray, ray:tsimport { geometry, math } from "cc"; // Construct a ray that points to the Z-axis from the origin const outRay = new geometry.Ray(); geometry.Ray.fromPoints(outRay, math.Vec3.ZERO, math.Vec3.UNIT_Z);
Use the camera to construct a ray emitted from the camera origin to a point on the screen.
tsimport { geometry, Camera } from "cc"; // Take the example of a script mounted under Camera const camera = this.node.getComponent(Camera); // Get a ray emitted from the screen at (0, 0) const outRay = new geometry; camera?.screenPointToRay(0, 0, outRay);
Note.
- First you need to get a reference to a camera component or camera instance.
- The order of the interface parameters exposed by the camera component and the camera instance are different.
Interface Introduction
Cocos Creator provides a set of raycast detection functions based on the physics engine.
The interface is currently provided by PhysicsSystem and has the following two classes.
raycast
: Detects all colliders and records all detected results, obtained viaPhysicsSystem.instance.raycastResults
. The interface returns a boolean value indicating whether if the ray intersects with any collider or not.raycastClosest
: detects all colliders and records the result of the detection with the shortest distance to the ray, obtained viaPhysicsSystem.instance.raycastClosestResult
. Also returns a boolean value same asraycast
method.
Note.
- The detected object is a physical collider, and the corresponding collider component in the scene panel is a collider component, e.g. BoxCollider.
- The object returned by the detection result is read-only and reused, and the corresponding result is updated after each call to the detection interface.
Common examples of raycast detection of nearest objects based on camera position and screen coordinates.
let ray = new geometry.Ray();
this.camera.screenPointToRay(eventMouse.getLocationX(), eventMouse.getLocationY(), ray);
// The following parameters are optional
const mask = 0xffffffff;
const maxDistance = 10000000;
const queryTrigger = true;
if (PhysicsSystem.instance.raycastClosest(ray, mask, maxDistance, queryTrigger)) {
const raycastClosestResult = PhysicsSystem.instance.raycastClosestResult;
const hitPoint = raycastClosestResult.hitPoint
const hitNormal = raycastClosestResult.hitNormal;
const collider = raycastClosestResult.collider;
const distance = raycastClosestResult.distance;
}
The following code demonstrates how multiple objects can be detected:
const worldRay = new geometry.Ray(0, -1, 0, 0, 1, 0);
// The following parameters are optional
const mask = 0xffffffff;
const maxDistance = 10000000;
const queryTrigger = true;
const bResult = PhysicsSystem.instance.raycast(worldRay, mask, maxDistance, queryTrigger);
if(bResult){
const results = PhysicsSystem.instance.raycastResults;
for (let i = 0; i < results.length; i++) {
const result = results[i];
const collider = result.collider;
const distance = result.distance;
const hitPoint = result.hitPoint;
const hitNormal = result.hitNormal;
}
}
Parameter Description
worldRay
: the ray in the world spacemask
: mask for filtering, you can pass in the group to be detected, default is 0xffffffffmaxDistance
: the maximum detection distance, default is 10000000, do not passInfinity
orNumber.MAX_VALUE
at this timequeryTrigger
: whether to detect the trigger
Result Description
The result of the ray detection is stored by PhysicsRayResult, mainly with the following information.
collider
: the collider that hitdistance
: the distance between the hit point and the start of the rayhitPoint
: the hit point (in the world coordinate)hitNormal
: the normal of the face where the hit point is located (in the world coordinate)
Related test cases can be found in the GitHub repo.
Line Stripe Cast
Line stripe cast/sample points cast is supported in Cocos Creator since v3.7. There are two methods lineStripCast
and lineStripCastClosest
which can be used to cast a line stripe in the physics world to detect colliders.
Interface description
These two methods which encapsulated the raycast
method are convenient to use used when checking whether one or more colliders are hit by the line stripe provided by the samplePointsWorldSpace
parameter.
lineStripCast: Collision detect all collider and record all the detected results
tslineStripCast (samplePointsWorldSpace: Array<Vec3>, mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean;
lineStripCastClosest: Collision detect all collider, and record the ray test results with the shortest distance
tslineStripCastClosest (samplePointsWorldSpace: Array<Vec3>, mask = 0xffffffff, maxDistance = 10000000, queryTrigger = true): boolean;
Parameters
samplePointsWorldSpace
: Sample points/line stripe in world spacemask
: mask for filtering, you can pass in the group to be detected, the default is 0xffffffffmaxDistance
: the maximum detection distance, default is 10000000, do not passInfinity
orNumber.MAX_VALUE
at this timequeryTrigger
: whether to detect the trigger
Return values
It will return true when the line stripe intersects with other colliders, but the result of detection is stored in PhysicsSystem.Instance.lineStripCastClosestResult
and PhysicsSystem.Instance.lineStripCastResults
which can be referred in the following contents.
Example
Use lineStripCastClosestResult
和 lineStripCastResults
to fetch the invoking result if these methods return true.
if (PhysicsSystem.instance.lineStripCastClosest(sampleArray, ...)) {
const result = PhysicsSystem.instance.lineStripCastClosestResult;
...
}
The properties of lineStripCastClosestResult which type is PhysicsLineStripCastResult inherited from PhysicsRayResult are as follows:
id
: The index of the line stripe when collidedcollider
: the collider that hitdistance
: the distance between the hit point and the start of the rayhitPoint
: the hit point (in the world coordinate)hitNormal
: the normal of the face where the hit point is located (in the world coordinate)
The description of lineStripCast
property is an array of PhysicsLineStripCastResult
which is detailed from the above. The code example is as follows:
if (PhysicsSystem.instance.lineStripCast(sampleArray, ... )) {
const results = PhysicsSystem.instance.lineStripCastResults;
for (let i = 0; i < results.length; i++) {
const result = results[i];
...
}
}