Performance. Choosing between rays and checking for mesh intersections

Hi all. I have a question about choosing between rays and checking for mesh intersections.
In the RTS, I implement an attack between units, so I need to search for a target, within the attack range, while the unit is not doing anything. First of all, the implementation through rays came to mind, which I did, but this gives rise to several nuances (including if the target is higher by y), and then I thought about intersections, because I can make each unit an invisible sphere with a radius equal to firing range and track units that are inside this sphere.
Which of these will be more productive? Since, unfortunately, I do not have an understanding of the resource requirements of both options.
The code I’m currently using looks like this:
findTarget() {
try {
if (!this.meshcore) { return }
// calling multiple times in one call
let hit = false
for (let index = 0; !hit && index < 10; index++) {
hit = this.castFindTarget()
}
} catch (err) { console.log("findTarget: ", err.message) }
}

castFindTarget() {
try {
this.meshcore.rotation.y += 0.02
var origin = this.mesh.position;
var forward = new BABYLON.Vector3(0, 0, 1);
forward = vecToLocal(forward);
var direction = forward.subtract(origin);
direction = BABYLON.Vector3.Normalize(direction);
var ray = new BABYLON.Ray(origin, direction, this.range);
var hit = scene.pickWithRay(ray, this.predicate);
if (hit && hit.pickedMesh && hit.pickedMesh?.type !== “rock”) {
this.attackTarg(hit.pickedMesh.parentObject.unid, hit.pickedMesh.parentObject.type)
return true
}
} catch (err) { console.log("castRay: ", err.message) }
}

vecToLocal(vector) {
let m = this.mesh.getWorldMatrix();
return BABYLON.Vector3.TransformCoordinates(vector, m);
}

predicate(targ) {
try {
return targ.type === “rock” || (targ.type === “core” && targ.parentObject.playerid !== this.playerid)
} catch (err) { console.log("predicate от: ", this.playerid, err.message) }
}
I understand that usually it would be necessary to provide the code on the playground, if necessary, I can compose it, but here the question is more about the overall performance of the approaches than about the specific code.

It sounds like all you need in that case is a proximity test. Would a simple 3D distance check between units work for you? (sqrt((a.x-b-x)^2 + (a.y-b.y)^2 + (a.z-b.z)^2) Raycasting is for when you need to know specifically which point on which triangle is being detected.

this was generally my primary option, before the rays, but in this case I would need to go through all the moving meshes each time and calculate the distance between the unit and them. I consider this to be a much higher cost.
This option can be used when there is a list of grids in the required distance, and already iterate over this list, looking for the nearest one. But again, it is possible to throw rays at the desired distance more productively. I don’t know it :slight_smile:

I would test this instead of assuming. Raycasts are very expensive, and a distance check is not expensive. If all you need is relative distance for comparing, you can even skip the square root in the distance check. Just compare squared distances. It’s hard to imagine the distance comparisons would be slower than raycasts, but then again I don’t fully understand how your project works.

Imagine the usual strategy, warcraft or starcraft) In general, I can’t sort through all the objects for each object and find the range between them. The number of searches will grow in the square. Even with 100 objects, this is already a lot :slight_smile:

That’s what’s the ray intersection code is doing, anyway. Same thing for mesh intersections, except if you enable octree.

But what @kloklike suggests is probably the best, the calculation is very simple and looping through the meshes should not be a problem. If it is, you can set some acceleration structure (like an octree) to find the list of potential targets.

Did I understand you correctly that throwing even one beam “under the hood” iterates over all the meshes on the scene and simply checks if they meet the requirements (beam range - distance between meshes, direction, position, etc.)? I thought it was something like creating a line-segment and checking the intersection with it, based on pseudophysics … I’m apparently still very stupid))
Does this mean that the performance between casting rays and manually sorting through all the meshes in the scene, with further calculation of the nearest one, will be approximately equal?

Yes, but how could it be otherwise? The system must check all the meshes to see which ones meet the requirement. You can speed up the checks by reducing the number of meshes to be checked using an acceleration structure, such as an octree.

Yes, more or less, but you will save some object creations if you do the loop + distance calculation yourself instead of relying on the ray/mesh intersection code.

You can also try using a physic plugin, as they have functions to perform intersection tests that can be faster than Babylon’s own functions.

3 Likes