New property: PVInstance.Visible

As a Roblox developer, it is currently frustrating, difficult, and badly performing to “unrender” PVInstances (Models and BaseParts). In order to create systems for LOD, or temporary object cleanup, developers must either unnecessarily delete the PVInstance, iterate over all of its descendants and explicitly set LocalTransparencyModifier (also recording their original values and hoping nothing else touches it in the meantime), or move the object very far from the camera. All of these methods come at a significant cost in terms of performance.

In my game, Aftermath, I very frequently move models and base parts in bulk to a very far away location to prevent rendering them from unnecessary distances. I use a similar system for zombies which aren’t within a reasonable distance. And I use this technique for building interiors that don’t need to be rendered 95% of the time. This is a common technique employed by many games, since reparenting objects tends to be far more expensive, and destroying objects often invokes a large cleanup job (I would often see upwards of 60ms), and LocalTransparencyModifier is too unreliable and slow in large models.

In cases where collisions aren’t a concern, and all we need to do is make it so a PVInstance is not rendered it would be ideal to do this quickly and efficiently. This idea has been proposed many times in the past, but having a property such as Visible is commonly used in the engine, and it behaves exactly the same as I’d expect it to in this case every where else its being used.

Just speculating, but it seems as though something like this already exists in the engine with the new culling system, so a similar property being exposed to developers would be awesome.

16 Likes

How would this work for LOD? Don’t you care about disabling collision also in that case so you don’t have multiple pieces of collision geometry stacked on top of eachother?

Also, moving the objects to a distant location is not as bad a solution as you make it out to be.

The Roblox engine is designed around a physics simulation, where moving objects is designed to be a fast-path, as simulated objects will be moving every frame. Taking advantage of that fast-path for swapping things out is actually just a reasonable use case.

In the case of LOD, I don’t ever need collisions for my other LOD levels, or at least that’s a sacrifice I’m willing to make, although I’m sure the engine itself could do a far better job of handling LOD for us. Having control over visibility just seems like a simpler solution that we’re more likely to get, and has other uses as well.

I don’t mean that moving objects is a bad solution, it’s really the only solution we have. But moving objects, especially if those objects involve a humanoid, has always been a bottleneck for me.

Take my use-case on building interiors for example, if I want to move an interior to, say, 0, 10e8, 0 and I use streaming in my game, I have to move the interiors into the camera on the server (so I can validate bullet collisions and other server-sided simulations), recreate the interiors on the client and move them around as needed. If I don’t do this, then the objects will be streamed out and incur a large deferred delete job.

Moving an interior takes roughly 0.15-0.2ms on my PC (which isn’t a slow computer) since there are a lot of objects involved in that move. Presumably I could improve this performance by welding everything together (just a hunch, I haven’t tested this). The collisions are not at all a bottleneck for me, render time is, so moving them really isn’t necessary, and incurs a lot of extra work for the client and far more complex validation for bullets on the server side. I would also imagine it causes a lot of updates in the physics BVH or KD-tree, whatever it is that’s used internally.

Another good example I can think of in my game are my ground items. I have thousands of items scattered around the map, they’re not rendered on the server, but the information used in generating the models is streamed to the client using the built in streaming. These items never have any collisions at all, and some of them have a very good amount of detail… which we could reduce, sure. But if I could just not render these at all until players are within their desired visibility radius for them then that seems like a great option to me. Currently, I “cache” these models to the extent that I am able to and I move them far away and that works, but it begs the question in my mind “why can’t I just not render these?”

I certainly don’t mean to dog on moving objects at all as a solution. You definitely know more about the internals than I do, but given my use-case here does it not make sense to just be able to flick a switch and it doesn’t render at all anymore? Perhaps the LOD use-case isn’t a great one, I was trying to make this more broadly applicable. Most games don’t need to go to the trouble that my game needs to in order to run well on the client. Perhaps all of this could be solved with more granular streaming capabilities though. In any case, seems like a great capability for the engine to support in my mind.

Are you moving it as just a bunch of anchored parts in a Model?

If you weld it together into an assembly with only the root part being anchored that will fully take advantage of simulation and make it much faster to move.

2 Likes

This should really be documented. I was under the assumption that using PivotTo (and maybe in certain cases BulkMoveTo) was always the best option for giant models.

Hypothetically, if there was a model with 2000+ BaseParts (MeshParts, Parts etc.), and I move it in these two ways:

  • all parts unanchored and with a WeldConstraint to one root part, and just setting the CFrame of the root part
  • all parts anchored and calling :BulkMoveTo after calculating the relative CFrames based on a root part

Would the first method with the welds be faster? Is it a significant difference?

Welded will be significantly faster than not welded.

Note that this doesn’t mean you shouldn’t use PivotTo: You should just also weld the object if you plan to be moving it a lot. PivotTo is smart enough to take advantage of you having welded the object to perform better.

Using PivotTo isn’t just about performance, it’s about being able to control object placement through the pivot without caring about the specific parts within the object.

2 Likes

In this case, I definitely agree with @Mauio64, this comes as a big surprise to me… So far, I’ve been under the assumption that the overhead of firing .Changed signals as well as processing all the physics was slower than :BulkMoveTo. Thank you for clarifying this!

Learned something new! This is interesting.

Does this not seem like a lot of “gotchas” in order to address the issue of the OP? It’s a pretty terrible workflow to have to have specialty knowledge of the backend of how assemblies are managed by Roblox.

3 Likes

If you think that’s a lot of gotchas, a “visible” property puts it to shame in complexity.

If you have an engine that’s not built from the ground up with a concept of visible things get very complicated trying to implement it.

  • Should visible impact physics?
  • Should visible impact selection?
  • But selection is based on physics (via raycasts), so these are somewhat coupled.
  • Should visible impact audio (simulated audio / what happens if I play a sound in a non-visible object?)
  • If I make a part of a welded model invisible, should the model get cut “cut in half” and fall into two pieces?
  • Should particle emitters and other effects in the invisible object be invisible?
  • Should it be possible to easily find out if an object is visible? (or do I have to manually walk up the tree looking if any parent is visible)

A lot of these questions have very different answers on what you would like in different scenarios so making a “visible” that actually does something people would be happy with is quite challenging.

Most of these can be developer controlled IMO.

It should not impact physics.
Unless I’m misunderstanding this, it should not impact selection, since there’s already a Locked property. It should behave the exact same as a transparent part but for a whole PVInstance instead.

No, this can be checked with a quick if-statement before playing the audio.

No.

No, this can be checked with an if-statement.

Yes.


This feature request is also similar to New property: Model.Visible.

I think it should just make it invisible. And none of the above questions should have any different behavior than default.

1 Like

I believe a better name like “CanRender” would solve all of your proposed issues.

This is extremely straight forward and clearly indicates that this dictates whether or not it is rendered and nothing else. The other “CanX” properties can be used to handle physics processing and what not.

As for your final issue - whether or not it should be possible to easily find out if an object is “visible”/rendered - yes it should be. Either through a function or a complimentary property such as “IsRendered”.

3 Likes

If you make a part’s Transparency 1, are physics, selection, audio, or welds affected? Generally, no, as far as I’m aware.
Thus, I think it stands to reason that setting a model to not render wouldn’t affect any of that either. @SoCalifornian made a good suggestion in naming it CanRender instead of Visible; I’d also expect this property to not render any “special effect” instances (Particles, Sparkles, Beams, Lights, etc)

For other cases, I think it’s reasonable to say developers can either move or reparent the model, as we do right now.

1 Like