BasePart.CollisionsDisabled, BasePart.VoxelShadowsDisabled

These two properties are meant to help with positioning and resizing huge, non-physical objects (such as backdrops), or for improving performance when dealing with small details.

Together, these two properties can serve to make parts act similar to parts with a *Mesh object in them, replacing much of *Mesh object’s functionality.


CollisionsDisabled will disable all collision detection for a part. Unlike CanCollide, CollisionsDisabled will turn off all calculations for collision detection. Collision detection is still done with CanCollide parts for things like the Touched event. On a CollisionsDisabled part, Touched will never fire and it will never fire Touched on another part. Constraints, Body* objects, and gravity will still affect the part.

Its purpose is to lessen the performance impact of positioning and resizing huge parts, and to lessen the performance impact of having many small, detailed parts in one location.


VoxelShadowsDisabled will disable voxel lighting calculations for a part. Some parts, such as backdrops or constant, skybox-like elements, should not ever cast shadows. On these parts, doing any voxel lighting calculations is a waste of performance. This is also sometimes true for very small parts, which would never cast a shadow anyway.

Note that these parts still receive color and lighting information from the voxel grid, but they cannot cast shadows too it. This is similar to if a part had a *Mesh object in it with a huge scale.


A poll to gauge developers’ interests in these two properties:

  • CollisionsDisabled
  • VoxelLightingDisabled

0 voters


Performance Issue Reproductions

I made some ‘bug repros’. A ‘stutter’ is defined as the FPS dropping below 30 (where it normally rests at 60). Feel free to open up the scripts and make the parts invisible in order to demonstrate that these are physics performance issues. These are done with anchored, CanCollide = false parts.

Changing CFrame, Size, then CFrame according to this post:
LargeCollisionsSize.rbxl (12.8 KB)
Run in studio run mode.

Parenting w/ changing size: LargeCollisionsParenting.rbxl (12.8 KB)
Run in studio run mode. This parents the part to nil, changes the size, then parents it back in order to circumvent the collision checks being done when size is changed normally. There is still stutter on every size/parent change.

Changing CFrame without parenting: LargeCollisionsCFrames.rbxl (12.7 KB)
Run in studio run mode.
Small changes in CFrame do not cause stutters below 30 FPS. Large ones (such as the ones in this example) do.

Many small parts in one location: ManySmalls.rbxl (13.3 KB)
Run in studio play solo mode.
If you put the parts between the character and camera, the FPS drops greatly due to collision checks involved with raycasts.
If you walk through the parts with a sideLength of 10 (1000 parts) it will stutter.
I admit that this is not a huge issue, though it might be if the character had many parts, for example. It might also be an issue on less powerful computers and platforms, such as Android and iOS.

2 Likes

Is this true? Or is it only true when the CanCollide=false part has a TouchInterest inside (created when listening on the Touched event)?

Edit: ok, it is true. I didn’t expect that answer. :stuck_out_tongue:

Wouldn’t it make more sense to just not do collision detection while changing size/position?

imo changing size and position shouldn’t have collision detection in the first place

3 Likes

I can see the reason in that, but there might be backwards-compatibility issues. This would also limit what can be done on the future.

Take, for example, an elevator that is made by only setting the CFrame property. Currently this works okay going up and down, even if it’s not a good solution to the need for an elevator. If changing CFrame did not do collision checks, then players and objects would not move up or fall down with the elevator.

Another issue I can think of is that this is probably not (easily) possible with the current physics system ROBLOX uses.

If it were implemented this way, then the performance benefits of not calculating collisions for static objects will be lost. I think this is not a big deal for big objects, but in my experience it would be a big deal for many small, detailed physics objects in one place.

I think you misunderstood

Currently when changing position or size, a part’s position will be changed to sit on top of any parts currently in its way

This is what makes resizing large parts/parts in an area near a bunch of parts expensive (because of all the collision checks)

That’s the behavior I think should be removed

1 Like

I’ve experienced performance issues with setting the CFrame alone of large objects. I did not experience the same issue when using a small part and a large mesh. The two biggest differences are physics collision checks and voxel lighting grid calculations. This is what leads me to believe that collision checks of some sort are done when an object’s CFrame is updated.

I definitely agree with the Size property change you are suggesting, though. I think it’s also worth mentioning that I’ve tried setting a large part’s Parent to nil, changing the size, then putting it back to circumvent the collision checks. I still had performance issues, so it cannot be only Size changes causing the performance issues.

First off, lighting is cheap. If VoxelShadowsDisabled is implemented, it probably won’t be for performance reasons.

CFrame should be one of the fastest properties to set because it doesn’t cause a recluster. It might cause some kind of physics update, but have you checked the microprofiler?

do this instead

part.CFrame, part.Size, part.CFrame = part.CFrame, newSize, CFrame.new(3.4e38, 3.4e38, 3.4e38)

I am aware that calculating voxel lighting should be pretty cheap. I will admit that it is entirely possible that I am wrong about what causes these performance issues, though. Physics is the only thing I can think of that can cause these performance issues.

The microprofiler tells me nothing about why setting CFrame (from the CFrame setting reproduction place I provided) causes the issue.

Screenshot ![](upload://sgZgrYhzceTnLAzez7YcZxmS1xw.png)

That’s over 100 ms to move a single part. Maybe CFrame should be cheap, but in some cases (big parts) it is not.
My main guess as to why is because it has to do some sort of physics update for the whole area. It is obviously not rendering: if it was simply rendering, moving huge meshes around would have these issues too. That leaves the things that large physics objects do that meshes do not: collisions and voxel lighting.


I replaced the update method in the ‘parenting’ reproduction place with the sizing code you provided. Looking at the microprofiler, Size takes up almost nothing, it turns out that CFrame is the cause almost entirely! Sadly, it again does not tell me anything else about what’s going on.

Screenshot ![](upload://rBdagkQjv9lnVFaSPTf2wKeZ1CE.png)

I am also adding this place as a reproduction in the original post.


We still do not know why these performance issues happen. I still think it is caused by physics calculations, but maybe I am wrong. I would nevertheless like to see it fixed somehow, even if the only way to fix it is a toggle to remove some sort of feature of the part (like collisions).

“Do you want a new feature?” - “Hell yeah!”

I don’t believe the benchmarks in this post accurately classify the behavior. Specifically:

  • None of them as far as I can see show any indication that lighting/shadowing is a problem for small parts or big parts. Adding a way to disable shadow casting may conflict with implementing alternative shadow techniques and as such is not a good idea by default.
  • There are some frames in some benchmarks that have “relocateGrid” in the profile stats - this is related to lighting but it does not normally happen in character-based game and is mostly an artefact of non-character play testing you’re doing. Even this is reasonably small, I guess, for the size of the part being moved/resized…
  • The small part case is indeed catastrophic; however, it’s not really the raycast per se being a problem as far as I can see, rather it’s a sheer number of raycasts performed (80+ ray casts per frame at 0.5 ms each…). We should look into this, this suggests camera script can exhibit problematic behavior in pathological cases
  • The part resize/cframe in certain cases is also super slow, but disabling collisions is not likely to address this directly. Specifically, there’s two separate parts of cframe/size update that can be slow: broadphase update and narrowphase update.

Broadphase update involves updating the spatial lookup tables to help other algorithms find the part. The challenge is that there are many systems that need this information - collision detection, lighting, streaming, path finding, to name a few. You can’t just disable this basically.

Narrowphase update involves updating pairwise information between parts. This can be a huge source of the problem for CanCollide true parts, and occasionally even for CanCollide false due to specifics of how we discard contacts, but I want to say that it’s not likely to be the issue for your use case - without looking at detailed stats my gut feeling is all these tests bottleneck in broadphase.

We are very much aware of current limitations in broadphase performance; we had some promising prototypes last year on potential solutions for this which we are planning to look into next year.

2 Likes

Ah, btw the fact that each ray cast takes 0.5 ms in the small part case I think is another artifact of the existing broadphase implementation - having many parts clumped in the same area creates some pathological behaviors due to how it’s structured internally. So yeah, this is basically a big issue for workloads like this and we need to revamp the said data structure.

1 Like

That makes sense. It’s great to hear an explanation and that solutions are already being worked on.

I have a few questions, though.

Would I be right to think that parts with *Mesh objects (especially with extreme scale and offset) have ‘inaccurate’ broadphase data for their rendered models? The fact that developers can limit the impact of the part during broadphase updates is extremely useful for performance, but that’s not the only advantage. Some parts are only meant to be seen, not walked on, or pathfound around, or anything physical, and should not use any normal distance-from-render-center sort of calculation for determining visibility or streaming. For example, large backdrops/scenery should render regardless of distance from the camera or quality level, and should have very little performance impact when moved since they have no physical interaction. Any sort of normal part alone fits neither of these requirements.

Currently, the best way to achieve these things is a part with a *Mesh object. Those are being replaced and seemingly phased out. I think this is the heart of what I was looking for in this feature request, and here I specifically addressed performance issues, but there’s more to it than that. It took some discussion to realize what I was really looking for.

How much value do you think there is in implementing a separate physics model for parts, in the same manner as how *Mesh objects render separately from their physics models? Do you consider it to be a priority? Do you consider it an important step in phasing out *Mesh objects (assuming that’s one of ROBLOX’s goals)?