Wouldn’t an implementation of this use a loop anyway?
It would be faster on the C++ side, and we wouldn’t need to worry about interacting other scripts that use part.Transparency/LocalTransparencyModifier, decal.Transparency, pointLight.Enabled, particleEmitter.Enabled, etc.
Mainly this feature would be an alternative to removing/destroying models, and would keep the model’s physics running at the same time.
To some degree, I feel inclined to create the counter-argument that it is easy to pre-compile a table/list of all the parts in a model that can easily be used to toggle this all. It wouldn’t be difficult to create a little module to do this quite easily. But it still stands that it would be much faster outside of Lua, considering the possibility of hundreds (maybe thousands?) of parts that may need to be toggled instantaneously. Also your points about conflicting with other scripts that interact with transparency is a good point.
I’m bumping this because my co-developer brought up that this exact feature would be great for building inside studio a couple days ago, and now because it seems like models will be getting level of detail functionality soon.
If the (visual) geometry of a model is completely switchable at runtime, a property like the one suggested should be able to be implemented too.
Would be pretty neat since a side project of mine already has a script that uses the LocalTransparencyModifier, but there is also a LOD system which should be able to override it.
I had to create a wrapper to hold and apply the value when a model enters/exits a render sector, but it can get a bit laggy when there are over 500 parts to load.
Summary
Add Visible property of type boolean to Model class, where when it’s set to false all of its current and future descendants will not render but sounds, physics, replication, and anything that does not produce image will remain unaffected. To put it simply, the sole concern of the property is visual.
Motivation
The ability to hide objects is a very common operation within game development, and it is a fundamental feature of any game engine. Roblox as a game engine already has similar feature where it is available in various forms, such as:
- The Visible property on the GuiObject abstract class.
- The Visible property on the GuiBase3d abstract class.
- The Enabled property on the LayerCollector abstract class, from which a common class like ScreenGui inherits.
- The Enabled property on the UIStroke class.
- The Enabled property on the UIGradient class.
The closest one from this list in terms of functionality is the LayerCollector, which is commonly utilized in a form of ScreenGui instance, where the Enabled property disables rendering its descendants that fall under user interface category when set to false.
Outside of Roblox, many notable game engines implement this feature:
- Godot has “visible” property on “Node3D” instances.
- Unity has “enabled” property on the “Renderer” component which can be found in a “GameObject”.
- Unreal Engine has a “Set Visibility” function in their blueprints.
- GameMaker has “visible” property on their instances.
Besides prior work, there are countless use cases for this feature, where it would not only come handy but prevent many bugs, and make code more reliable and future proof. Currently developers will often resort to writing code that may look something this:
This is a simple solution which often is used as part of the arguments against implementation of the feature, however, it has major drawbacks. The function works under the assumption that the model is only composed of parts (Part, MeshPart, etc.) and nothing else, although it works just fine in plenty of cases, it is not sufficient in many other cases, one of those cases are car games where many of them have cars without interiors, and often placing player’s character inside of the car may not enough to hide it, thus developers need to hide the character itself.
Player characters are incredibly unpredictable due to accessories that the players can equip on their characters, as the developers are not in control of what instances and their behavior might be present within them, and it has become even more unpredictable since the introduction of public UGC items that lets practically any user on the platform (as long as they meet few basic requirements) to create their own accessory which any player can acquire and equip on their character. Additionally, with each new version release of the engine, a new instance may be introduced which will not be accounted for by older code. This forces developers to have to constantly keep up-to-date and perform occasional maintenance to keep their game functioning properly.
To hide the player character, and the accessories within them, developers often resort to more complex functions unlike the one shown earlier, and they often modify properties of BaseParts, Decals, Textures, ParticleEmitters, Lights, Beams, and countless more. Additionally, they have to retain their original values so that they can be restored later when making the character visible again.
For example: In Tower Defense Simulator’s “FPS mode” players are meant to be invisible to prevent obstructing the active player’s view so that they can aim their weapon at the incoming enemies. However, I’ve noticed instances where certain player accessories remain visible (as shown in the image below) while they’re supposed to be hidden, and some properties don’t revert to their original values upon exiting FPS mode, which result in unintended alteration to the player’s character appearance.
These issues likely stem from the difficulty in accounting for all possible properties, instances, and their associated logic. Similarly, many games featuring vehicles (as mentioned earlier) face similar complications when attempting to hide characters upon entering a vehicle.
Besides countless properties to account for, developers may face even greater challenges when the models have descendants added to or removed from while being hidden. Models may also contain instances whose properties continue to change while hidden.
For example, if a developer were to make a game like Murder Mystery 2, and add a feature where murder can become invisible for short period of time, and the character happened to carry a knife equipped with an animated glowing rainbow skin, the developer would have to first disable the effect before being able to hide the player’s character who’s carrying the knife. This might be simple, but as the game grows and becomes more feature rich, it will become increasingly more difficult and annoying to deal with, and it will make a major impact on the code complexity.
Performance is also a concern given switching visibility of objects is a common operation in games. For example, take the “Skinned Avatar” from the built-in Roblox Studio plugin “Rig Builder”, the sample character is composed of 308 instances. That’s just a sample, an advanced avatar made by a user may end up creating an avatar with a lot more. If a game can have 20 players, that’s already 6160 instances.
Having to account for descendants being added, removed, and properties constantly changing in all of those models would be impractical due to the performance cost.
The proposed Visible property would provide developers with a straightforward solution to these challenges, reducing the need to handle numerous edge cases, potential conflicts with future Roblox updates and UGC creator innovations.
Implementing this feature would greatly simplify the development process and enhance the overall quality and consistency of games on the Roblox platform. As a player, developer, and observer of these issues, I believe this addition would benefit both developers and users alike.
Workarounds
There are 4 common workarounds that developers can employ to change the visibility state of their models.
Traditional Method
Acquire the descendants of a model and set all the appropriate properties (e.g., Transparency, Enabled, Visible, etc.) to values that will make them either visible or invisible. Typical approach may look something like this:
Position Method
To make the model invisible: Move the model very far away (either through Position, CFrame, or PivotTo). To make the model visible again: Move the model back to its original location.
Parent Method
To make the model invisible: Set its parent to ReplicatedStorage, or any other instance that does not render 3D instances. To make the model visible again: Sets its parent back to the original parent.
ViewportFrame Method
To make the model invisible: Place the model inside a ViewportFrame. To make the model visible again: Remove Viewport Frame and temporarily place the model in a ReplicatedStorage for at least a frame before parenting it back to its original parent. This method was mentioned by Stellar (@rabbi99) in one of their posts.
Drawbacks
There should be no significant drawbacks associated with one additional property to the Model class. The logic for not rendering objects appears to be already there, and ReplicatedStorage alongside ViewportFrame as workarounds methods are both proof of that.
Seems quite useful ngl, would probably use it quite often.
This is so real
I use the “offload things by banishing them to replicatedstorage” technology because Model.LevelOfDetail is tied with StreamingEnabled and no sane person would ever reference everything to ever exist for all time with WaitForChild() spam
The workarounds that devs have to go through in order to have some semblance of a proper instance loading/offloading system is unreal
For StreamingEnabled, you could also just make interactable stuff and humanoid entities (Players and NPCs) to be always persistent, and geometry stuff will use regular streaming since those don’t have any logic
But custom LOD will always be better
Please!
Deparenting and parenting models is a stupidly expensive operation right now, especially if they contain a lot of parts or unions or affect a lot of shadows.
Sounds intriguing and very useful
Bump much needed and very useful
I would love to create a resource for semi-frustum culling where objects are hidden if they are completely hidden by walls or terrain.
Reparenting or moving the object far away is unfeasible because of slow performance and cases where the collision still needs to exist or to preserve momentum.
Bump!
This would be so useful.
This would be very useful in my game where I very often hide models that I know can’t be seen. I’m currently just setting LocalTransparencyModifier but this would be much more fitting and hopefully faster than using transparency.
preach, it makes optimizations very hard, having a visible option or even some kind of bulk method would do so much good in large complex experiences.
It’s a bit silly that we have AI generated textures, materials, script-assistant and patchnotes, yet we don’t have extremely basic engine features like this.
Support.
This feature is crucial for any game engine. It’s quite funny that the CEO of Roblox claims to have respect for the community, but yet none of the developers at Roblox seem to even acknowledge this missing feature.
But what can you do? Well, finding workarounds. I don’t like giving up.
I like to play around with the Roblox engine, pushing its limits. And I just now found out you can make anything invisible but still simulated in the workspace by putting them inside of a ViewportFrame inside the workspace like so:
It’s not perfect, as you still need to parent things, which can cause problems in some cases. But at least you won’t have to worry about any Transparency, Enabled or Visible property.
Then again, Roblox needs to add this feature themselves, similarly to the CanvasGroup for UI, which was a literal game changer.
You can also make the part permanently invisible by creating a ViewportFrame, parenting the part inside it then parent it back to its original parent in the same frame.
Yeah, that’s actually a problem with this method I just realized. I am currently trying to find a way to fix that.