Hi, I’ve encountered an issue with DragControls. When I have DragControls applied to multiple model parts (around 15), the FPS drops significantly when I move the mouse around, even without dragging anything. From what I’ve observed, enabling DragControls triggers a pointermove
event that performs a raycast, which appears to severely impact performance. Could you look into what might be causing this issue?
Hi Vydymil,
The performance issue you’re experiencing with DragControls is likely related to the extensive use of the pointermove
event and the raycasting that occurs with each movement, even when not dragging. This can significantly impact FPS, especially when multiple DragControls are active.
Suggestions to Improve Performance:
-
Optimize Raycasting: Consider reducing the frequency of raycasting. You could throttle the raycasting process or implement a debounce function that allows raycasting to occur only after a certain period of idle mouse movement.
-
Use Accelerated Raycasting: There’s an option to utilize accelerated raycasting using the
three-mesh-bvh
. Make sure to enable this in your raycasting options to improve performance. You can check your raycasting setup to integrate this feature effectively (see the documentation). -
Limit Active DragControls: Instead of applying DragControls to all parts, consider only enabling them on essential components during user interaction. This approach reduces the load on the system.
-
Adjust Drag Logic: Modify the
onPointerMove
method to only process raycasts when necessary (i.e., when mouse movement exceeds a certain threshold). This can prevent excessive updates when the pointer moves only slightly (see the documentation).
Relevant Code Example:
Here’s a modified snippet you could implement in the DragControls that throttles raycasting:
private raycastThrottleTimeout: NodeJS.Timeout | null = null;
onPointerMove(args: PointerEventData) {
if (this._isDragging || this._potentialDragStartEvt !== null) {
if (this.raycastThrottleTimeout) clearTimeout(this.raycastThrottleTimeout);
this.raycastThrottleTimeout = setTimeout(() => {
this.performRaycast(args); // Method for handling the raycast operation
}, 100); // Adjust milliseconds as needed
args.use();
}
}
You might want to fine-tune the timing and conditions based on your specific application for optimal results.
Feel free to ask if you have further questions or need clarification!
1 replies left - Get a PRO license for more AI replies.
thread_FDBNi2Gp2k56zbRo8HOlQdrR
Reply to this message to continue the conversation
Hi, could you provide the following info:
- does your scene have compression enabled/disabled?
- are you testing in a production build?
- did you disable mesh LODs?
- how many vertices does your mesh have?
- are you using skinned meshes with dragcontrols?
- which needle engine version are you using?
Compression is disabled.
This is not a production build, just a local export from Unity.
Since it’s a local Unity export, I don’t believe there are any mesh LODs.
The entire model where this happens has around 160,000 vertices.
The meshes are normal, not skinned.
I tested it on version 3.50.0-pre and want to test it on the latest version, but I’m having difficulty with the license.
What difficulties do you refer to? If it’s regarding connecting your existing subscription i have just replied your Email
Please try updating and also enabling AutoCompression in ExportInfo or on a production build. With LODs and mesh compression performance is generally much better
Thank you for the quick response. The license difficulties were resolved via email.
Regarding the DragControls issue, I tested it with compression enabled, and the performance improved significantly. However, this solution isn’t feasible for us, as enabling compression increases the export time by several minutes, which creates a significant delay for our graphics team when working on and testing models.
Is it necessary for DragControls to fire a raycast on every mouse action when they are in the scene? In my opinion, this approach seems quite wasteful for certain modes. Am I missing something?
I understand, you tested with AutoCompress now right?
When you make a production build you will have the same optimizations as with AutoCompress but it will only happen once you want to update the project for the web - so you can disable the AutoCompress toggle again for faster iteration speed in the editor but performance in the development server will be slower.
This is done by the eventsystem for components that implement the onPointerMove
event function (which is the case for DragControls) where it’s necessary to perform hit tests to fire the event. We’re already deploying quite a few strategies under the hood to make this faster than default three.js (using BVHs and raycasting against lower resolution meshes). That being said there’s still room for improvement for future updates
Yes, I tested it using AutoCompress and ProductionBuild. The issue is that the performance on the development server without compression is almost nonexistent—just moving the mouse around drops the FPS from 60 to 10, and interacting with the model feels more like a PowerPoint presentation.
Do you have any suggestions on how I could locally modify DragControls to improve performance specifically in dev mode? Alternatively, would it make sense to create a simple custom DragControls implementation for development that gets replaced with your optimized implementation in production builds?
Could you share the project with us via a Bugreport? We’d like to take a look to better understand your setup and scene.
I’ve sent the bug report. If something doesn’t work, please let me know. Also, this issue is more apparent with bigger and more complex models; with the simpler ones, it works fine.
Thank you, we received the report
Hello, the bug report does not contain any DragControls components. Was that a mistake? Could you again upload a scene containing the right components?
The model should initially have only one script. DragControls are added through code and enabled via the UI after “unlocking” the model. Are the DragControls not working after “unlocking” the model?
Ah I understand, I wasn’t aware of that. Thank you
Apologies for the misunderstanding; I forgot to include it in the bug report description.
Hello @vydymil what you can do as a workaround for dev right now is adding this code snipped to one of your scripts: e.g. above ModelSettings. This will remove the event methods of DragControls that are causing the raycast to run every cursor update.
Note that the count of DragControls does not affect performance. Raycasting is handled centralized by the engine. The engine already tries to only run raycasts when necessary (e.g. when a component expects certain events). So by removing these methods from the DragControls class and since no other component in your project is using those events we can temporarly stop the engine from running raycasts during pointermove events.
if (isDevEnvironment()) {
// @ts-ignore
DragControls.prototype.onPointerEnter = undefined;
// @ts-ignore
DragControls.prototype.onPointerMove = undefined;
// @ts-ignore
DragControls.prototype.onPointerExit = undefined;
}
export class ModelSettings extends Behaviour {
...
Thanks for the quick help. This gave me a better understanding of the event system.
Hello @vydymil
I actually have another update: there was a bug in the raycasting system where the better raycast was not used and instead it was silently falling back to slow raycasting.
With the better raycasting I get solid 60 FPS even with tons of debug logs. This will be fixed in the next alpha release!