Optimized Interactive Grass Plugin

Interactive Grass Gif

Hey everyone,

New Interactive Grass Plugin! :seedling:

I’m super excited to introduce my new interactive grass plugin! This makes grass and flowers in your game move when something touches them. Inspired by ADRENALXNE/Dev1n’s Interactive Grass tutorial/showcase, but I’ve added a bunch of new features for optimization, aesthetic, and configuration.

How to setup? :thinking:

Simply click the “Install” button in the menu to install everything, then select your grass parts and select “Tag Grass”, and thats all!

How to update? :repeat:

Simply click the “Update” button in the menu and it’ll update your code to the latest version!

Key Features :key:

  • Realistic Movement: Makes the grass move like it would in real life.
  • Easy to Use: Simple to add to any game or virtual project.
  • Adjustable: You can tweak the settings to get the perfect look and feel.

Options :blush:

Install Interactive Grass :seedling:

  • Installs the scripts and sets everything up instantly.
    image

Uninstall Interactable Grass :wastebasket:

  • Uninstalls all the scripts and removes all tags.
    image

Tag Grass :heavy_plus_sign:

  • Tags the selected objects with “Grass” to make them be interactable.
    image

Untag Grass :heavy_minus_sign:

  • Untags the selected objects to make them not interactable.
    image

Tag Hitbox :green_square:

  • Tags the selected objects to make them a hitbox/interactable with grass.
    image

Untag Hitbox :red_square:

  • Untags the selected objects to make them not a hitbox/not interactable with grass.
    image

Update Grass Physics :arrow_up:

  • Updates your scripts with the latest available code.
    image

Create Hitbox :blue_square:

  • Creates a hitbox for the selected object, helpful if you want to make the hitbox size of a object smaller
    image

Config: :gear:

GrassPhysics.Config = {
	WindShake = {
		Enabled = true,  -- Enable/disable wind shake effect, ENABLING THIS DOES NOT ADD IT INTO YOUR CODE! You must set it up yourself, but turn this on if you have it shake the grass using wind.
		ScriptPath = {
			Path = Players.LocalPlayer.PlayerScripts.WindControllerClient -- Path to the wind shake script, not the module, the script that requires it, example: Players.LocalPlayer.PlayerScripts.WindControllerClient
			} :: ScriptPathConfig
		} :: WindShakeConfig,

	OcclusionCulling = {
		HideGrass = {
			Enabled = false  -- Enable/disable hiding grass when its not visible on the screen, can improve performance but may cause bugs.
		},                  -- ONLY KEEP ONE OF THESE ENABLED, THE OTHER ONE FALSE
		DisablePhysics = {
			Enabled = false  -- Enable/disable disabling grass physics when the grass isn't visible on the screen, can improve performance.
		},
	},

	Sound = {
		Enabled = true,  -- Enable/disable sound effects
		Volume = 0.1,  -- Volume of the plant sound effects (0.0 - 1.0)

		PitchRange = {  -- Range for randomizing pitch of plant sounds
			Min = 0.8,
			Max = 1.0
		},

		Reverb = {  -- Reverb settings for the sound
			Enable = false,
			DecayTime = 2.0,
			ReflectLevel = 0.5
		},

		Spatial = {  -- Spatial audio settings
			Enable = true,
			RolloffMode = Enum.RollOffMode.Linear,
			MinDistance = 10,
			MaxDistance = 100
		}
	},

	Tween = {
		Duration = 1.6,  -- Duration of animation tweens in seconds
		EasingStyle = Enum.EasingStyle.Elastic,  -- Easing style for animation tweens
		EasingDirection = Enum.EasingDirection.Out,  -- Easing direction for animation tweens
		TweenName = "pivotTween"  -- Name for the tween instance
	},

	Physics = {
		HitboxRadius = 200,  -- Radius around the hitbox within which effects will be activated
		Intervals = {
			UpdateInterval = 0.1,  -- Update interval for checking activations and camera positions
			CameraUpdateFactor = 2,  -- Factor to control how often camera updates are checked
			ActivationUpdateFactor = 2  -- Factor to control how often activation updates are checked
		}
	},

	Grass = {
		Tag = "Grass",  -- Tag used to identify grass objects, changing this can break the plugin
		HitboxTag = "Hitbox",  -- Tag used to identify hitbox objects, changing this can break the plugin
		Transparency = 1,  -- Transparency level of the hitbox

		CollisionResponse = {  -- Collision response settings for the grass
			Enable = true,
			Friction = 0.5,
			Bounce = 0.1
		}
	},

	Camera = {
		FieldOfViewThreshold = 2,  -- Additional degrees to the camera's field of view for angle checks
		MovementThreshold = 1  -- Minimum movement in position or rotation to consider camera as moved
	},

	SoundAsset = {
		SoundEnabled = true,
		SoundLimit = 50, -- Keep this low, but not too low or your sounds will sound ugly.
		SoundMappings = {
			Grass = {
				SoundId = "rbxassetid://8008438167", 
				VolumeRange = { Min = 0, Max = 0.25 }
			},
			GrassHitbox = {
				SoundId = "rbxassetid://8008438167", 
				VolumeRange = { Min = 0, Max = 0.25 }
			},
			Hitbox = {
				SoundId = "rbxassetid://8008438167", 
				VolumeRange = { Min = 0, Max = 0.25 }
			},
			--[[Add more sounds as needed, example
			Flower = {
				SoundId = "rbxassetid://0", 
				VolumeRange = { Min = 0, Max = 0.1 }
			},]]
		}
	},

	Debug = {
		EnableLogging = false,  -- Enable or disable debug logging
		ExtraLogging = false, -- Extra debug logging, may flood your output; must have Enable Logging set to true for this to work 
		LogFrequency = 5  -- Number of updates between log entries
	}
}

Planned Features: :bulb:

  • More debugging options, such as toggling different sections (Toggling WindShake debugging, toggling sound debugging, toggling hitbox debugging, etc) since right now turning on logging/debugging can lag your game due to the number of prints in the output.
  • Option to make a model into grass, which will create a hitbox and well everything inside the model to that part and tag the hitbox
  • Entire modernistic UI Overhaul

Testing Place: :hammer:

Interactive Grass Testing Place

:warning: If the grass and buttons don’t work in the testing place, this is most likely due to something loading too late/quickly, please rejoin to test it again, I’m working on fixing this.

Download Link :point_down:

Interactive Grass Plugin

Please feel free to inform me about bugs or suggestions to improve this aswell as ideas for future features! :grin:

Would you use this in your games? (Test it here before voting😉)

  • Yes :+1:
  • No :-1:
  • Maybe :thinking:
  • If it was free :money_mouth_face:

0 voters

37 Likes

this resource is awesome, installing right now.

2 Likes

How does this compare to terrain grass, performance-wise?

3 Likes

V1.2 Release Notes :tada:

Bug Fixes :hammer_and_wrench:

  • Grass no longer twitches when the player stands still
  • Repeating sound issues resolved

New Features :star2:

  • Multiple Sounds Support: Play different sounds for various parts (e.g., Grass :seedling:, Flower :cherry_blossom:)
  • Expanded Config:
    • Sound mapping customization :musical_note:
    • Support for spatial audio and reverb effects :headphones:

Enjoy the update! :rocket:

Glad you enjoyed it, V.2 is out with bug fixes and more configurations.

Its designed to be efficient because it only activates grass near the player, and in tests with 25,000 grass meshes, there was only a small drop in FPS, which shows it’s pretty good at handling lots of grass without major lag. Works well for smaller game maps with lots of detail, but for large open-world games, use this with Roblox’s terrain grass for the best performance. Although, even if you are using Roblox’s terrain grass in for example an open world game, you can add hundreds of flowers and plants and make them interactable using this module and it won’t cause any lag. (For reference, the current game file/play testing place uses like 6k grass meshes, and there is no lag)

2 Likes

Important Note

I’ve decided to simplify things by switching to a paid plugin. It installs everything you need with one click and updates outdated code easily. This means I won’t have to provide separate game files and models for each version anymore. It also includes tagging features, so you don’t need additional plugins like Tag Editor to tag and untag things.
image

Hi,

How is this different then other free interactive grass scripts like

Thanks

1 Like

Hey, so mine doesn’t have major features that differentiate it from other free interactive grass scripts, the differences are mainly just simplicity since it takes like 10 seconds to set up, and being able to configure with the vast config in mine to adjust everything to your liking, I know this isn’t enough to justify mine being $5, which is why I’m planning on figuring out solutions as to more optimization, other players being able to see you move around in grass without lag, aswell as support for shaking your grass like how the wind shake module does, cause rn if you try to combine this with the windshake module its buggy. I’m looking for feedback on how I can improve my plugin to make it stand out, since right now it was just released today and doesn’t stand out that much.

It’s all good. So how would you go about making it so others can see the movement?

I assume you are currently using local scripts on the client?

1 Like

Yes, I’m using local scripts on the client. I’m not entirely sure how I could make it so others can see the movement but maybe remote events and fire it all to clients? so it wont tween the grass on the server but on everybodies client

V1.3 Release Notes :tada:

Wind Shake Support :leaves:

New Configuration Section :gear:

  • New “WindShake” section in the configuration. :dash:
	WindShake = {
		Enabled = false,  -- Enable/disable wind shake effect
		ScriptPath = Players.LocalPlayer.PlayerScripts.WindControllerClient,  -- Path to the wind shake script, not the module, the script that requires it
		},

New Notification UI :bell:

  • UI Notifications will pop up when you install the plugin, tag grass, untag grass, and uninstall the plugin, as well as errors. It will also include sounds, rather than only using the output to print messages! :yum:
    image

What this is really good for is making tall grass that is different and unique apart from terrain grass. :slight_smile:

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

1 Like

Hey, 2 questions

Does this use actors?
What performance methods do you use?

Besides that, pretty neat.

3 Likes

V1.4 Release Notes :muscle:

Performance Features :hammer_and_wrench:

  • 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.
Video Showcase

Enjoy the update!

Yup, it looks the most satisfying with tall grass too. Thanks for the suggestions on improving the performance, I’ll look into it.

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.

I have done similar projects which were fish, and boids (birds insect) simulation.
Performance is very important, also offloading calculations to the server is good practice. Great job on your plugin! Glad to see you implemented the performance upgrades.
Here’s a link to something.
“Boids” Flocking Swarming Simulation Luau Algorithm - Library Animated Bird+Bats+Insects V.1.3 [Open Source] FREE MODEL - Resources / Community Resources - Developer Forum | Roblox

Womp womp, resource went paid, time to make my own version or use an alternative.

3 Likes

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?