-
-
Notifications
You must be signed in to change notification settings - Fork 19
Raycasting
Raycasting is at the core of any anti-esp or anti-xray. It is therefore unsurprising that it is a target of heavy optimisation. Some examples of raycasting algorithms from other projects are this one from PlayerCulling and this one from RayTraceAntiXray. In the name of optimisation, these methods are both almost completely impossible to understand without deep analysis.
RaycastedAntiESP's raycast implementation appears primitive in comparison. It is less than half the length, and uses objects instead of primitive fields. At first glance this gives the impression that RaycastedAntiESP's must be much slower, but the opposite is true. In benchmarking, RaycastedAntiESP can consistently raycast about twice as fast1 as either of the other linked implementations.
How is this possible? Firstly, looks can be deceiving. Just because the source code of RaycastedAntiESP's algorithm appears to allocate about 5 objects per raycast doesn't mean this actually occurs. All objects used are consistently scalarised by the JVM2. This means we get the much easier-to-read (and maintain) syntax of object-oriented programming, with all the same speed of primitives as the other two implementations.
Both of the other implementations linked use 3D DDA voxel traversal algorithms. This is generally considered the best sort of traversal algorithm for voxel-based scenarios such as Minecraft worlds. However, RaycastedAntiESP uses a "naive" ray-stepping algorithm. This significantly reduces the number of calculations needed per step, providing most of the speed increase. While DDA algorithms are more technically correct since ray-stepping can sample blocks several times or miss blocks entirely, for a situation such as RaycastedAntiESP this does not matter. If a block is missed, that means only the edge of the block was in the path of the ray, and therefore a player would be able to see behind the block anyways, so treating that space as visible is valid. Repeatedly sampling the same block just causes an additional memory access, which while a source of inefficiency is more than cancelled out by the reduction in calculations needed to find the next block.
1: Performance was tested by using RaycastedAntiESP as a base, just modifying the raycast algorithm. This eliminates other differences between the plugins as a factor affecting the results. RaycastedAntiESP's algorithm had a median of approximately 215ns/raycast while PlayerCulling's took approximately 380ns/raycast, and RayTraceAntiXray's took about 420ns/raycast. Note that this doesn't mean that their algorithms are "bad", they are still highly optimised for their purpose.
2: This is not guaranteed by the JVM spec, which is why many opt not to rely on it, but I believe that the improved maintainability justifies the unproven risk of a JVM failing to optimise the raycasting method.