New Properties: CanRender/Renderable

As a Roblox developer, it is currently too difficult and costly to toggle whether Instances are rendered.

The two existing approaches are:

  • Approach A: Iterating over all descendants and manually setting Transparency / Visible / Enabled properties. This is slow, requires bookkeeping, and isn’t reliable for large models.
  • Approach B: Moving Instances far away so they no longer render. This is hacky, unintuitive, and still wastes processing.

Neither option is performant, ergonomic, or sustainable at scale. They’re workarounds, not solutions.

There are numerous applications where developers today rely on costly workarounds that this property pairing would solve cleanly:

  • World/Environment Unloading: In games like Car Crushers 2, systems unload parts of the world when players don’t need to see them (e.g., building interiors or exterior chunks). Currently this is done by iterating transparency or reparenting, which wastes performance. With CanRender, developers could exclude large sections of the environment from rendering without disrupting collisions or physics.
  • NPC/Mob Culling: In games like Aftermath, NPCs outside a reasonable range are forcefully teleported to prevent rendering. With CanRender, mobs could remain simulated in place — colliding, pathfinding, and interacting — while being visually excluded until needed.
  • Character Culling: In games where players occupy the same space but shouldn’t see each other (e.g., private houses, instanced events, or layered worlds), developers currently have to reparent character models or hack around with transparency and property modifications. With CanRender, characters could be hidden instantly without disrupting gameplay logic, physics, or networking.
  • Cutscenes/Transitions: Developers often need to temporarily de-render props, backgrounds, or set pieces without deleting them or breaking welds. CanRender would make this efficient and predictable.
  • Helper Volumes: Trigger volumes, bounding/anchor parts, or spatial query-only regions should never draw, but must still exist in the world for collision or queries. Today, this requires managing transparency or special-case models. With CanRender, these can remain entirely excluded from rendering while retaining function.

The goal of this feature request is to address the concerns raised here and to properly standardize the expected behavior explicitly.

The proposal is to introduce two new properties:

  • CanRender (bool, default true)
    Explicit developer-controlled toggle for whether an Instance (and its descendants) are eligible for rendering.
  • Renderable (read-only bool)
    Indicates whether the Instance is actually renderable — i.e., CanRender is true on it and all of its ancestors.

This mirrors the existing CanX property style (CanCollide, CanQuery, CanTouch), giving developers predictable, narrowly scoped control.

In the original thread, there was ambiguity raised about a more vaguely named property “Visible” — would it affect physics, selection, audio, welds, effects, hierarchy, etc.? By scoping the proposal narrowly to rendering only, all of those become non-issues:

  • Physics → Already controlled by CanCollide, Anchored, Massless, etc.
  • Selection / raycasts → Tied to physics, not rendering.
  • Audio → Unaffected, sounds continue to play.
  • Welds & assemblies → Stay intact; only visuals are hidden.
  • Effects → Emitters still simulate, but visuals are not drawn.
  • Hierarchy → Renderable resolves ancestry automatically, so no manual tree-walking is needed.

This provides a clear, predictable contract: developers can be confident that CanRender affects only rendering — never physics, audio, or selection.

For example, this allows Volumes to still be collided with or act as Spatial Querying Volumes while still being excluded from the Render Pipeline, which would not be possible if collision or querying properties were bound to this new property and functioned off the principle of being “Visible”.

By introducing CanRender and Renderable, Roblox would give developers fine-grained, performant, and predictable control over rendering — without the ambiguity of a Visible property and without entangling physics, audio, or selection systems.

This follows Roblox’s established CanX property convention, solves longstanding pain points, and enables better LOD, streaming, and optimization patterns that are critical for large-scale Roblox experiences. By giving developers precise control over rendering, Roblox empowers them to build more performant, scalable, and visually dynamic games.

55 Likes

This would be incredible. I’d love to see it implemented!

5 Likes
4 Likes

Before posting on the DevForum next time, I highly suggest reading the post you are responding to.

I clearly indicate that this post is in response to an existing staff reply about the ambiguities and problems with a “Visible” property and I include a direct link to it (which you would’ve seen had you read the post). Even worse, this staff reply is included in the first post you linked.

This post has a foundational difference from existing posts on the DevForum and especially those that you linked, there should be no association or connection to the concept of a “Visible” property and this post.

12 Likes

Then why was it not made as a response to that same post instead of effectively creating a duplicate feature request?

2 Likes

I did over a month ago on the original thread. It was a similar proposition to the one I outlined here. Also, again, there is supposed to be no association or related concept to the idea of “Visibility” (that concept should be dead in relation to what it originally meant).

This post basically acts as a proper RFC or standardization for the expectation of a feature like this. No other “related” post on the DevForum is structured like this and clearly outlines what to expect, which leads to confusion or arguments about how it should behave. You can see this quite clearly on the original post I referenced with the staff members reply.

You simply cannot do that with a single reply to a post. It makes sense to cry “duplicate feature request” when it truly is just asking for something addressed prior by somebody else with slightly different wording or use-cases. However, when it’s a suggestion that clearly improves upon existing requests and removes issues raised by staff, you just can’t do the same, that’s like saying “competing standards” shouldn’t be a thing in the real world either (which just borders on ridiculousness).

None of this conversation is constructive nor beneficial to the actual post itself and is off-topic, so I won’t be engaging with these type of replies to this post in public anymore. If you have a problem, feel free to DM me about it, but it’s extremely clear this post is independent of any other previously posted feature requests and is significantly different in intent to warrant not being labeled as a “duplicate”.

13 Likes

I absolutely love the idea, but I have a relatively simple issue.

Why do we need two properties? In my mind, almost always, CanRender is enough because it’s not an indicative of actual rendering in a frame. Occlusion culling and other stages in the rendering pipeline could potentially overcomplicate Renderable. Otherwise, it would be an exact copy of CanRender but one we can’t change.

There might be of use to this, but I simply don’t see it so I will appreciate it if you clarify!

2 Likes

Because being able to efficiently and performantly figure out if an instance is being rendered is incredibly valuable for any intensive code that doesn’t need to run if the instance isn’t even visible. A property indicating that the instance is being rendered is much more desirable than the alternative of iterating that instances entire ancestor hierarchy in order to determine its current render status every time we need to know it.

9 Likes

I am starting to see why Renderable might be of use; simply find out if a PVInstance can be unrendered of it an ancestor has its CanRender set to off, but then again, the infrastructure you need to track Renderable can be at the end of the day be used to set CanRender to off anyway.

Also, a Property indicating something to be rendered right now is again, complicated. I saw a comment from a Roblox engineer that is working on Occlusion Culling that this form of property is complicated, I will try to add it to here if I find it.

1 Like

It shouldn’t need to keep track of all possible methods of an object not rendering, just the one that is explicitly in control of the developer and of which any number of instances in its hierarchy can influence the result of.

Keeping track of occlusion culling is better suited to a separate feature request, and in my opinion, is better off exposed as an API where a developer is given more flexibility on its use cases instead of a property.

4 Likes

@TheGrimDeathZombie already covered the main aspect — being able to quickly tell if an Instance is allowed to be rendered. “Renderable” is just a cached state so developers don’t need to recompute it themselves.

You mentioned:

Occlusion culling and other stages in the rendering pipeline could potentially overcomplicate Renderable

That’s an important distinction to call out. “Renderable” is strictly about whether the Instance (or any of its ancestors) has “CanRender” set to true. It does not reflect whether it was culled or passed through other stages of the rendering pipeline.

Originally I considered a property name like “IsRendered”, but that came with two major issues:

  1. It implies write-ability and risks confusion with “CanRender”.
  2. More importantly, it implies whether the object is actively being drawn by Roblox’s rendering pipeline.

That’s out of scope and not what this feature is asking for. “Renderable” was chosen because it cleanly implies whether an object can be rendered — not whether it currently is.

An object being culled doesn’t mean it isn’t renderable — it just means it wasn’t drawn that frame. If the pipeline is even considering the Instance in the first place, then it’s renderable.

This distinction is important. While developers may eventually want a property that tells them if something is actually being rendered, that’s a separate feature request. In this case, what matters is knowing if the engine would even consider rendering the instance in the first place. Exposing that state directly saves developers from recomputing ancestry checks every frame in performance-sensitive systems.

2 Likes

Maybe I’m missing something, but it doesn’t seem clear what classes these properties would be added to. Is it just for Models? BaseParts? Any PVInstance?

Also, what happens to SurfaceGuis/BillboardGuis that adorn objects with CanRender off? Do they continue to render? Do those along with ParticleEmitters have their Enabled property changed? What about constraints with their Visible enabled?

I’m also not convinced that a separate read-only property exposed solely for bookkeeping is warranted. From the sound of it, almost every instance would have to add it (BaseParts, Decals, SurfaceAppearances) which would just serve as more API bloat. The only argument for it is speculative ergonomics, remember.


You would just need to connect a callback to the root ancestor with :GetPropertyChangedSignal("CanRender").

Also, all the cases for performance that you list are already intended to be solved with frustum/occlusion culling. You’ll have better luck relying on engine rendering optimizations than doing them yourself (due to the inherent overhead of userdata bridging).

The problem with this proposed solution is that you need to factor in every ancestor of the instance that can influence whether or not it can currently render. Suddenly, instead of keeping track of one property which tells you this information efficiently and quickly, you are now needing to keep track of an entire instance hierarchy and that doesn’t even consider that in the event the instance is reparented you then need to update the hierarchy you are keeping track of.

1 Like

If you have a problem with objects suddenly becoming invisible under your feet, you should rethink how you’re structuring your game.

This isn’t like .Destroying, the engine can’t change how something renders without you programming it to do so. And if it can only change when you tell it to, why have a property/event in the first place? You already know and control when it changes.

This makes a very bold and unreasonable assumption that the code you’re writing is specialized towards a specific situation where you have full knowledge and control of all the parameters and completely ignores any developers writing general-purpose systems that would benefit greatly from the engine exposing information it should already know internally as a property.

1 Like

modern game engines like unreal engine dont necessarily need this logic and they just have a built visible render setting.. i think as much as it could be more efficient i think its overcomplicated to have that additional ‘Renderable’
for example: what is the point of running querys or checking objects to see if theyre renderable if this attribute is read only- in the case of this bool being false requires additional logic that overcomplicates the simplicity of the visible bool.
the simple visible bool function supersedes the functionality of this additional attribute as developers already are used to yielding threads or running wait functions from task library or rbxsignal on instances directly. double checking logic on each instance is a little overkill but i can totally see why this could be used.
i do agree though having a general render visible setting would be so much better than having to use the transparency property. maybe for a way for implementing this feature without any harm to existing frameworks and codebases is that objects that are already transparency = 0 should effect the render visibility setting and with that could possibly impact how instances are cached and provide possible performance boosts… but hey maybe thats a stretch

You’re right — I didn’t explicitly state which classes this would apply to, and that’s worth clarifying. The intended scope is Models, Folders, and BaseParts. Supporting containers and primitives directly should cover essentially every use case without adding unnecessary API bloat.

For adornments like SurfaceGuis and BillboardGuis, there are two possible directions:

  • Inheritance: they follow the “CanRender” state of the object they’re adorned to, since they rely on that object just as much as directly parented instances.
  • Exception: they can still render even if their adorned part is “CanRender” = false, which allows invisible anchor parts with visible GUIs.

Personally, I lean toward the inheritance model for consistency, but I think this is a good point for public input.

As for the concern about “Enabled” or “Visible” properties changing: this feature doesn’t touch those at all. “CanRender” is strictly about rendering eligibility — it doesn’t cascade into or override other properties.

On “Renderable”, this only needs to exist on the same classes that support “CanRender”. Think of it this way:

  • Primary Instances are the things you actually care about for rendering state (Models, Folders, BaseParts).
  • Attachment Instances — decals, textures, surface appearances, GUIs — are cosmetic layers on top of primaries. You’d never realistically check “Renderable” on these attachments, since they only exist to decorate or display on a primary object. They inherit state from the parent, so there’s no need to duplicate that property across every cosmetic instance.

Finally, regarding frustum/occlusion culling — those optimizations only decide what actually gets drawn. Roblox still processes and prepares those instances (including potential lazy-loading of textures/materials) before that point. “CanRender” lets developers explicitly tell the engine “don’t even consider this for rendering.” That’s an optimization no automatic culling system can replicate.

We shouldn’t encourage what is happening over at Unreal Engine, where developers neglect optimizing their game worlds because of Nanite. Likewise, we don’t want Roblox developers to become careless about optimization simply because frustum/occlusion culling exists. We should be empowering developers to expand upon the already great internal engine optimizations in ways Roblox cannot figure out algorithmically.

Once these points of discussion (e.g., adornment behavior, supported classes) reach a consensus, I’ll update the original feature request to reflect the clarified scope and behaviors.

Bump.

I understand this isn’t trivial to solve and requires thinking through, but it’s been very discouraging when the only staff acknowledgements are at this point just quasi-nitpicking hypothetical pitfalls with users’ propositions.

There should be no reason for me to have to abuse quirky engine behavior (that’s probably a bug, really) so that I can mark >10k parts invisible at once while still keeping collisions on. If it wasn’t for the engine bug I happened to stumble upon, the only solution would be to loop through every single part, and set its Transparency to 1–which is unfeasible from a performance standpoint.

3 Likes

Maybe I wasn’t clear enough. The userdata bridge between the Luau VM and the engine through instances will squish any developer attempts to optimize rendering like this. Trust me, everyone has tried this before. You could traverse every single model in the camera’s frustum and toggle its CanRender–cool–but it’ll probably take 5ms each frame for you to even finish updating all those properties in the first place.

The reason these kinds of manual optimizations work for systems such as WindShake is because they stop updating instances when they’re not needed. What you’re hoping to achieve with this feature won’t benefit from that approach because you’ll just be clogging the frame times with more userdata bridging anyways.

It only does that currently because a developer looking to hide or unhide an instance either has to move/reparent it or traverse its entire hierarchy, figure out what class its descendants are, and then handle those appropriately. Whereas a singular property like CanRender would only have the overhead of changing that one property.