Script bugs with multiple instances

hello all, I have this script that personally I am really impressed with, but i’m interested why it doesn’t work with multiple objects

module script

local maxRot = 5
local goalRot
local currentRot
local originRot

local grass = {}

function grass.new(blade)
	print(blade.Name)
	originRot = blade.Orientation
	print("new blade")
	wait(math.random(0,3))
	grass.move(blade,originRot)
end

function grass.move(blade)
	while wait() do
		print("moving blade")
		currentRot = blade.Orientation
		goalRot = originRot + Vector3.new(math.random(-maxRot,maxRot),math.random(-maxRot,maxRot),math.random(-maxRot,maxRot))
		for i = 1,10,1 do
			wait(.1)
			local moveGrass = grass.math(blade,goalRot,currentRot,i)
			blade.Orientation = moveGrass
		end
		print(blade.Orientation)
	end
end

function grass.math(blade,goalRot,currentRot,i)
	local x = goalRot.X - currentRot.X
	local y = goalRot.Y - currentRot.Y
	local z = goalRot.Z - currentRot.Z
	
	local newRot = Vector3.new(((x*(i/10))+(currentRot.X)),((y*(i/10))+(currentRot.Y)),((z*(i/10))+(currentRot.Z)))

	return newRot
end

return grass

server script

local grass = require(script.grassScript)

local grassFolder =script.Parent

for i,v in pairs(grassFolder:GetChildren()) do
	if v ~= script then
		task.spawn(grass.new,v)
	end
end

when testing with a single “grassblade” it works exactly as I would expect. However i’m confused because it seems like all the grass blades are moving the same and are being a lot more jittery. I tried adding the random wait to mix it up but they still manage to all sync up and it gets bugged out. if anyone could explain why to me, and also if you want give me some critique on the efficiency of the script, it’s all a learning thing for me.

Hi, sorry for the late response, but there are a couple of small errors and optimizations in your script that I have fixed below.

-- module script
local maxRot = 5

local function grass.math(blade,goalRot,currentRot,i)
	local x = goalRot.X - currentRot.X
	local y = goalRot.Y - currentRot.Y
	local z = goalRot.Z - currentRot.Z
	
	return Vector3.new(((x*(i/10))+(currentRot.X)),((y*(i/10))+(currentRot.Y)),((z*(i/10))+(currentRot.Z)))
end

local function grass.move(blade, originRot)
	local currentRot = originRot
	while wait() and blade.Parent ~= nil do
		print("moving blade")
		local goalRot = originRot + Vector3.new(math.random(-maxRot,maxRot),math.random(-maxRot,maxRot),math.random(-maxRot,maxRot))
		local moveGrass
		for i = 1,10 do
			wait(.1)
			moveGrass = grass.math(blade,goalRot,currentRot,i)
			blade.Orientation = moveGrass
		end
		currentRot = moveGrass
		print(blade.Orientation)
	end
end

return function(blade)
	print(blade.Name)
	print("new blade")
	wait(math.random(0,3))
	coroutine.wrap(grass.move)(blade,blade.Orientation)
end

-- server script
local grass.new = require(script.grassScript)
local grassFolder = script.Parent

for i,v in pairs(grassFolder:GetChildren()) do
	if v ~= script then
		task.spawn(grass.new,v)
	end
end

tell me if there are any errors. This should also make all of the grass blades wave separately since the variables for the grass rotation are now located locally in each blade rotation function. Tell me if you have any questions!

thank you this was very helpful! the only question I have is, the coroutine in the first function I believe is unnecesary? I did all the changes you made like make all the variables local variables, and it worked perfectly. I might be mistaken but I still have the coroutine in the script and I will keep it, im just wondering if that is genuinely needed. thank you for your help!

1 Like

Hi, the addition of the coroutine is really not necessary at all. However, it allows for the thread to end instead of waiting forever for grass.move to return something for potentially thousands of instances of grass blades. So basically, a miniscule amount of memory is saved with the use of a coroutine.

1 Like

a miniscule amount can be extremely useful in this case as there will be loads of grassblade instances

1 Like