What this is really good for is making tall grass that is different and unique apart from terrain grass.
In terms of performance advice, use ConnectParallel() where possible, actors, task.synchronize, task.desynchronize, and --!native, also occlusion culling for excluding objects physics not in view
Script now uses actors, task.synchronize, task.desynchronize, and --!native.
Occlusion Culling
Option to make grass not visible when the camera is not looking at it, although it’s not well optimized and leaving it not enabled is more smooth rather than enabled, spent like 10 minutes making it and realized its pointless and buggy so I scrapped it, but you can still enable it if you want I guess.
Yes, it uses actors. It uses a radius system to disable physics for grass that arent near you, so the game doesn’t constantly listen for those touch events. It also uses tags since tags are faster than looping through for example children in a folder or descendants in workspace with the names “Grass”. You should not experience any lag, especially if your grass is spread out and is a decal or has low polygons. Also has an okay occlusion culling system which can be toggled on or off which will move the grass not visible in the players camera to replicatedstorage.
In terms of occlusion culling, ROBLOX already does rendering occlusion culling, what your code should do is use that to determine whether to animate the grass or not.
local camera=workspace.CurrentCamera
local function IsInView(object,cameraViewportSize,key)
local objectPosition = camera:WorldToViewportPoint(object.Position)
-- Check if the object is within the camera's viewport
--print(objectPosition)
if objectPosition.X <= cameraViewportSize.X and
objectPosition.Y <= cameraViewportSize.Y and
objectPosition.Z > 0 then -- Z > 0 means the object is in front of the camera
return true
else
return false
end
end
local location=game.Players.LocalPlayer.PlayerScripts:WaitForChild("SmartBone-Actors")
local function dontcullsmartbone()
local cameraViewportSize = camera.ViewportSize
for i,v in location:GetChildren() do
v.Runtime.Rendered.Value=true
end
end
local function cullsmartbone()
local cameraViewportSize = camera.ViewportSize
for i,v in location:GetChildren() do
if v.Runtime:FindFirstChild("Sourceobj") and IsInView(v.Runtime.Sourceobj.Value,cameraViewportSize) then
v.Runtime.Rendered.Value=true
if v.Runtime.Enabled==false then
v.Runtime.Enabled=true
end
else v.Runtime.Rendered.Value=false
end
end
end
local camcfram=camera.CFrame
while true do
task.wait(.6)
if camcfram~=camera.CFrame then
--pcall(function()
cullsmartbone()
--dontcullsmartbone()
--end)
end
end
This is an example usage of occlusion culling that does not use many resources, but does not include the bounding box which is more relevant to larger objects. In my experience if you want to use that I would not do it every frame, but just use it to determine if you should animate the grass or not. Finally, a distance check could be done on objects in view, check if the grass should be animated or perhaps the fidelity of the animation such as the frames per second.
Alright, I’ll look into it. Isn’t occlusion culling gonna be a little unnecessary if I already have a radius system that disables the physics when I’m not near the grass?
well the radius system is good because it’s distance, occlusion culling is for objects that are not in view of the camera, such as objects behind the player’s field of view. It’s important not to do it every frame though as that could cause performance issues, this would allow the code to skip animating grass that is not seen by the player. It would be best to incorporate it into the radius calculation, so if the object passes the radius calculation it is checked for occlusion or vice versa
I’ve taken on the challenge of making the Interactive Grass plugin strictly typed. It’s now 99% complete! Additionally, I’ve optimized it a tad bit for better performance. Feel free to reach out on Discord if you’re interested: 6laise
For anyone that is bothered that it resets the orientation of the grass to a default direction which makes it a struggle to add variation (For example, grass that is rotated all over the place to make areas look better will all be set to straight upon joining), I’ve add a new option in the config SetOrientation = true which will on default will set the orientation when it sets up the grass. You can set this to false to keep it the same orientation, which will allow for more variation. Although, it adds a springy bouncy effect and It doesn’t really look as smooth as with it set to true. I have figured out a workaround to this, which I’d suggest you do rather than turning that option false. All you need to do is create a part and call it something like “GrassHitbox” (Make sure its around the same size as the grass) and then unanchor the grass, and weld those two together using weld constraints. Make sure you untagged the actual grass, and tagged the grass hitbox part. After this, you can group the hitbox and grass for organization, and rotate the grass to how you want. This’ll create that smooth look you want, while make the grass rotated to any way you want. (Update by pressing the install button again (If you prefer the new config option simply update again by pressing the install button which will overwrite the code.)
If anyones confused about what I mean, if you want a varied grass patch like this
Upon joining, the grass’s orientation will be set to this
Obviously this looks pretty bad, which is why I added this config.
Heres some videos comparing them: SetOrientation = true
SetOrientation = false
(edit one day later: ignore this post, ive removed the setorientation config and on default none of the grass’s orientation will be reset. ive found out a good way to make it smooth without resetting the orientation)
Thanks to everyone who bought the plugin I genuinely didn’t expect people to actually buy it, I would make it 100 robux if I could and feel free to request features or report bugs
Grass now supports multiple hitboxes; this means you can see when other people move around in grass, or when a car drives over a patch of grass.
Grass now resets back to its original position if you die while standing in grass.
Orientation no longer resets to a default position, so now you can add variation in your foliage.
SetOrientation config option removed
The plugin will no longer duplicate the “Hitbox” part in replicated storage when overwriting the code/updating the code.
When creating the players hitbox, it will use align orientations to keep the hitbox still rather than rotating it if you want to use a box for the hitbox
New Config Option
ExtraLogging – Extra debug logging, may flood your output; must have Enable Logging set to true for this to work
How can I make Interactive Grass support more things? (Cars, NPCs, Animals, etc)
To make Interactive Grass in Roblox support more things like cars, NPCs, animals, etc., follow these steps:
Create the Hitbox Part:
Insert a new Part into your game. You can choose any shape (e.g., Block, Sphere).
Set the Part’s Anchored property to false.
Set the Part’s Massless property to true.
Set the Part’s CanCollide property to false.
Set the Part’s CanQuery property to false.
Set the Part’s CanTouch property to true.
Position and Size the Hitbox:
Adjust the size and position of the Part to appropriately cover the object you want to interact with the grass.
Weld the Hitbox to the Object:
Insert a WeldConstraint into the Hitbox Part.
Set the Part0 property of the WeldConstraint to the Hitbox Part.
Set the Part1 property of the WeldConstraint to the object (e.g., car, NPC, animal) you want to interact with the grass.
Tag the Hitbox Part:
Ensure you have the Tag Editor plugin installed (you can find it in the Roblox library if you don’t have it).
Open the Tag Editor plugin.
Select the Hitbox Part and apply the Hitbox tag to it.
By following these steps, your interactive grass should now respond to the interaction of cars, NPCs, animals, or any other objects.