How to make Interactive Grass?

It will take some time until it is how i want it but i will post a video or something of it here :smiley: :+1: I will try to make that when animals walk through the grass will move too :ox: :deer:

2 Likes

Hey, thanks again for the hint how to do it! But I have a problem:

local grassfolder = workspace.Grass
local ts = game:GetService("TweenService")

while wait(.1) do
	for i, grass in pairs(grassfolder:GetChildren()) do
		
		grass.HitBox.Touched:Connect(function(hit)
			if hit.Parent:FindFirstChild("Humanoid") then
				
				local hum = hit.Parent:FindFirstChild("Humanoid")
				local movedir = hum.MoveDirection.Unit
				print(movedir.X, movedir.Z)
				local facevector = grass.PrimaryPart.CFrame * CFrame.Angles(math.rad(movedir.X), math.rad(0), math.rad(movedir.Z))

				local tween = ts:Create(grass.PrimaryPart, TweenInfo(.5), {CFrame = grass.PrimaryPart.CFrame * CFrame.Angles(math.rad(movedir.X), math.rad(0), math.rad(movedir.Y))})
				
				tween:Play()
				
			end
		end)
	end
end

ERROR:

16:03:04.042 - ServerScriptService.Script:15: attempt to call a table value
16:03:04.042 - Stack Begin
16:03:04.042 - Script 'ServerScriptService.Script', Line 15
16:03:04.042 - Stack End

I hope you can help me!

try doing ‘TweenInfo.new(0.5)’ instead

Oh gosh, i did not see that!!! :stuck_out_tongue_closed_eyes: Sry, but yea thx :smiley:

1 Like

It’s alright, btw don’t loop through them all, just have it like this instead

local grassfolder = workspace.Grass
local Players = game:GetService('Players')
local ts = game:GetService("TweenService")

for i, grass in pairs(grassfolder:GetChildren()) do
		local CharModel = hit:FindFirstAncestorWhichIsA('Accesory')

		grass.HitBox.Touched:Connect(function(hit)
			if Players:GetPlayerFromCharacter(CharModel) then
				
				local hum = CharModel:FindFirstChild("Humanoid")
				local movedir = hum.MoveDirection.Unit
				local facevector = grass.PrimaryPart.CFrame * CFrame.Angles(math.rad(movedir.X), math.rad(0), math.rad(movedir.Z))

				local tween = ts:Create(grass.PrimaryPart, TweenInfo(.5), {CFrame = grass.PrimaryPart.CFrame * CFrame.Angles(math.rad(movedir.X), math.rad(0), math.rad(movedir.Y))})
				
				tween:Play()
				
			end
		end)
	end

Get rid of the while loop.

Thanks, but i wont use GetPlayerFromCharacter cause I want to
be the grass interactible with animals.

sry for bad english

1 Like

Hi @AdaptabiI!
How can I make this code work better?

local grassfolder = workspace.Grass
local ts = game:GetService("TweenService")
local cooldown = false
local tweenMove
local tweenNormal

-----||      Settings      ||-----
local multiplier = 28
local tweentime = .8
local cooldown_devision = 8
local tweenInfoNormal = TweenInfo.new(tweentime * 2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
local tweenInfoTouched = TweenInfo.new(tweentime)




for i, grass in pairs(grassfolder:GetChildren()) do

	grass.PrimaryPart.Transparency = 1
	grass.RotateMain.Transparency = 1
	
	grass.HitBox.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			cooldown = true
			local hum = hit.Parent:FindFirstChild("Humanoid")
			local movedir = hum.MoveDirection.Unit
			
			if movedir.X > 0 and movedir.Z > 0 then
				
				local facevector = grass.RotateMain.CFrame * CFrame.Angles(math.rad(movedir.X * multiplier), math.rad(0), math.rad(movedir.Z * multiplier))
				
				tweenMove = ts:Create(grass.PrimaryPart, tweenInfoTouched, {CFrame = facevector})
				
				tweenMove:Play()
				
				wait(tweentime / cooldown_devision)
				cooldown = false
			else
				cooldown = false
			end
		end
	end)

	grass.HitBox.TouchEnded:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			local hum = hit.Parent:FindFirstChild("Humanoid")
			local movedir = hum.MoveDirection.Unit
			local facevector = grass.RotateMain.CFrame * CFrame.Angles(math.rad(0), math.rad(0), math.rad(0))

			tweenNormal = ts:Create(grass.PrimaryPart, tweenInfoNormal, {CFrame = facevector})
			
			tweenNormal:Play()

		end
	end)
	
end

Actually this works, but not everytime I touch the bush/grass…
Maybe you can help me :smile:

Thanks :sweat_smile:

1 Like

I’ve just made the code a bit neater, You’re not using your “cooldown” debounce correctly, it’s not being used at all infact, you should have it as a dictionaryvalue where CoolDown[grass] = false/true

local GrassFolder = workspace.Grass
local TS = game:GetService("TweenService")

-----||      Settings      ||-----
local multiplier = 28
local tweentime = .8
local cooldown_devision = 8
local tweenInfoNormal = TweenInfo.new(tweentime * 2, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut)
local tweenInfoTouched = TweenInfo.new(tweentime)

-----| Debounce Dictionary |-----

local CoolDown = {}

for i, grass in ipairs(GrassFolder:GetChildren()) do
	
	grass.PrimaryPart.Transparency = 1
	grass.RotateMain.Transparency = 1
	
	grass.HitBox.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			CoolDown[grass] = true
			local hum = hit.Parent:FindFirstChild("Humanoid")
			local movedir = hum.MoveDirection.Unit
			
			if movedir.Magnitude > 0 then
				
				local facevector = grass.RotateMain.CFrame * CFrame.Angles(math.rad(movedir.X * multiplier), math.rad(0), math.rad(movedir.Z * multiplier))				
				local TweenMove = TS:Create(grass.PrimaryPart, tweenInfoTouched, {CFrame = facevector})
				
				TweenMove:Play()
				
				wait(tweentime / cooldown_devision)
				CoolDown[grass] = false
			return end
			
			CoolDown[grass] = false
		end
	end)
	
	grass.HitBox.TouchEnded:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			local hum = hit.Parent:FindFirstChild("Humanoid")
			local movedir = hum.MoveDirection.Unit
			local facevector = grass.RotateMain.CFrame * CFrame.Angles(math.rad(0), math.rad(0), math.rad(0))
			
			local TweenNormal = TS:Create(grass.PrimaryPart, tweenInfoNormal, {CFrame = facevector})
			
			TweenNormal:Play()
		end
	end)
end

This is the updated code, .Touched is sometimes unreliable (i may be wrong about this because i remember there being an article showing the proper way to use .touched) So that’s why the .touched might not always fire, try use what i’ve supplied now though

1 Like

Thanks for fast reply! :smiley:

1 Like

Tried it! It works perfectly!!! Now I will add wind simulation… but yea thx :smiley:

3 Likes

No problem, again DM me when it works i’d like to see it :slight_smile:

Hi again!
I hope that this is the last Question I ask you…
so, i made wind Simulation… but… when I put the Wind strengh to 0.9999998999999999 you can´t really see the wind Animation, but when put the strengh to 1.0 it is too strong and it spines around way too much!

--||     Wind     ||--
while wait(tweentime * (tweenbackMultiplier/2)) do
	if wind then
		for i, grass in ipairs(GrassFolder:GetChildren()) do
			local windtween = TS:Create(grass.PrimaryPart, tweenInfoWind, {CFrame = grass.PrimaryPart.CFrame * CFrame.Angles(math.random(0 - windStrengh, 0 + windStrengh), math.rad(0), math.random(0 - windStrengh, 0 + windStrengh))})
			windtween:Play()
			if not touching then
				wait(tweentime / 1.2)
				local normaltween2 = TS:Create(grass.PrimaryPart, tweenInfoWind, {CFrame = grass.RotateMain.CFrame * CFrame.Angles(math.rad(math.random(-1, 1)), math.rad(0), math.rad(math.random(-1, 1)))})
				normaltween2:Play()
			end
		end
	end
end

windStrengh is a NumberValue in the script.

Hope you can help me! again… :smiley:

2 Likes
while wait(tweentime * (tweenbackMultiplier/2)) do
	if wind then
        local CFrameDifference = CFrame.Angles(math.random(-windStrengh, windStrengh), math.rad(0), math.random(-windStrengh, windStrengh)
		for i, grass in ipairs(GrassFolder:GetChildren()) do
			local windtween = TS:Create(grass.PrimaryPart, tweenInfoWind, {CFrame = grass.PrimaryPart.CFrame * CFrameDifference)})
			windtween:Play()
			if not touching then
				wait(tweentime / 1.2)
				local normaltween2 = TS:Create(grass.PrimaryPart, tweenInfoWind, {CFrame = grass.RotateMain.CFrame * CFrame.Angles(math.rad(math.random(-1, 1)), math.rad(0), math.rad(math.random(-1, 1)))})
				normaltween2:Play()
			end
		end
	end
end

It probably occurs because you are multiplying the current CFrame by the new ‘CFrameDifference’ that i’ve put in, You will want to check that the ‘windtween’ is not called more than once, just make sure it’s not doing it over and over again (check your while wait(tweentime * (tweenbackMultiplier/2)) do)

Copy the code i sent as it is now because i’ve edited it a bit, Come back to me if it still doesn’t work

5 Likes

hey, TheHeroGamer001 I was looking at this topic and it seems very interesting. Is it possible if you could send a video of how it turned out, I want to try and implement this into my game but I don’t know how it turned out so I would like to see an example first!

how did you get the wind system to work I have been trying to figure it out but I am not able to. i have no idea how you implemented it into the script

As shown here, this is how I would get the wind to work. It has been 2 years and i haven’t been developing for awhile so I may not have the answer for you right away.

But the idea is that you have ‘wind gusts’ so at every time interval (tweentime * (tweenbackmultiplier/2)) it will apply a tween to each grasspart transforming it to move in the direction fo the wind.

Try using the quoted piece of code and if possible, DM me about this so we are not necrobumping this thread

2 Likes

I’ve had the same issue with grass and wanted to make one and I found that your solution is very helpful but I can’t seem to know where exactly to place everything or whether if the script is local or not.
image
image

And I also have this error in output

I know it’s been a couple months and I’m very sorry about that :sweat_smile:

definitely a localscript; you don’t want the server micro-managing rendering tasks

2 Likes

Wild West does NOT use the interactive grass, that Roblox provides.


(Yes the grass mesh is quite primitive)
This is all done in a local script to compensate for the servers processing
(Meaning this does not replicate but it is very efficient)

(Layout Of grass and folder)
image

(Video of grass working and wind)

(RBXM (ROBLOX MODEL FILE) FILE)
grasssys.rbxm (33.2 KB)

(How to use the file)