I am working on a interactive grass system for my game so that the part moves when touched everything was going well until my original script stopped working when the gamed had StreamingMeshEnabled on so i had to rewrite the script. my new issue is I’m running into this error when writing the script and i am struggling to fix the issue. anyone have any ideas?
The error is on line 146
local PS = game:GetService('Players')
local CLS = game:GetService('CollectionService')
local RPS = game:GetService('ReplicatedStorage')
local TWS = game:GetService('TweenService')
local RS = game:GetService('RunService')
local hitboxFolder : Folder = Instance.new('Folder')
hitboxFolder.Name = 'HitboxFolder'
hitboxFolder.Parent = workspace
local player : Player = PS.LocalPlayer
local camera : Camera = workspace.CurrentCamera
local hitbox : BasePart = RPS.Hitbox
local grassData : {[BasePart] : {Top : Vector3, Pivot : Vector3, IsEligible : boolean, ActivationUpdated : boolean}} = {}
local hitboxes : {[BasePart] : {IsEligible : boolean, ActivationUpdated : boolean}} = {}
local activeParts : {BasePart} = {}
local playerConnections : {[string] : {CharacterAdded : RBXScriptConnection, CharacterRemoving : RBXScriptConnection}} = {}
local physicsConnections : {[BasePart] : {Touched : RBXScriptConnection?, TouchEnded : RBXScriptConnection}} = {}
local hitboxConnections : {[BasePart] : RBXScriptConnection} = {}
local rotationCFrame : CFrame = CFrame.Angles(0, math.rad(-90), math.rad(90))
local upAxis : Vector3 = Vector3.FromNormalId(Enum.NormalId.Back)
local tweenInfo : TweenInfo = TweenInfo.new(3.5, Enum.EasingStyle.Elastic, Enum.EasingDirection.Out, 0, false, 0)
local root3 : number = math.sqrt(3)
local timeCount : number = 0
local updateTimeCount : number = 0
local timeInterval : number = 0.1
local updateInterval : number = timeInterval * 2
local updateCount : number = 0
local activationRadius : number = 200
local eligibilityChanged : boolean = false
local hitboxEligibilityChanged : boolean = false
local lastCFrame : CFrame = camera.CFrame
local function tween(name : string, mesh : MeshPart, newCFrame : CFrame)
if mesh:FindFirstChild(name) and mesh[name]:IsA('Tween') then
mesh[name]:Destroy()
end
local tween = TWS:Create(mesh, tweenInfo, {CFrame = newCFrame})
tween.Name = name
tween.Parent = mesh
tween:Play()
tween.Completed:Connect(function()
tween:Destroy()
tween = nil
end)
end
local function activateHitbox(hitboxInstance : BasePart)
physicsConnections[hitboxInstance] = {}
physicsConnections[hitboxInstance].Touched = hitboxInstance.Touched:Connect(function(partTouched : BasePart)
if not (grassData[partTouched]) or not (grassData[partTouched].IsEligible) then return end
if (table.find(activeParts, partTouched)) then return end
activeParts[#activeParts + 1] = partTouched
local data = grassData[partTouched]
local direction : Vector3 = ((hitboxInstance.Position - partTouched.Position) * -Vector3.new(1, 0, 1)).Unit * partTouched.Size.Y/root3
local newLookAt : Vector3 = (data.Top + direction)
local newPosition : Vector3 = data.Pivot + ((newLookAt - data.Pivot).Unit * partTouched.Size.Y/root3)
if not (partTouched:FindFirstChild('TouchedFloor')) then
partTouched.TouchedFloor = true
local clone = RPS.TouchedFloor:Clone()
clone.Position = newPosition
clone.Parent = workspace
clone.Anchored = true
tween('TouchedFloor', clone, CFrame.new(clone.Position) * rotationCFrame)
tween('Color', clone, Color3.new(0, 1, 0))
end
local lookVector : Vector3 = ((newLookAt - partTouched.Position).Unit * partTouched.Size.Y/root3)
local rollAngle : number = math.rad(-90)
local newCFrame : CFrame = CFrame.new(partTouched.Position, partTouched.Position + lookVector) * CFrame.Angles(rollAngle, 0, 0)
local invertedCFrame : CFrame = newCFrame:Inverse()
local ray : Ray = Ray.new(invertedCFrame:PointToWorldSpace(newPosition), invertedCFrame:VectorToWorldSpace(-upAxis * 100))
local part, position = workspace:FindPartOnRay(ray, player.Character)
if part and part == partTouched then
tween('Activation', partTouched, newCFrame)
data.ActivationUpdated = true
else
local partTouchedSizeY : number = partTouched.Size.Y
local partSizeY : number = part.Size.Y
local ratio : number = partTouchedSizeY/partSizeY
lookVector = lookVector * ratio
newCFrame = CFrame.new(part.Position, part.Position + lookVector) * CFrame.Angles(rollAngle, 0, 0)
local partTouchedSizeYHalf : number = partTouchedSizeY/2
local partSizeYHalf : number = partSizeY/2
position = part.Position + ((partTouchedSizeYHalf - partSizeYHalf) * lookVector)
local pivot : Vector3 = data.Pivot
local height = ((newCFrame * CFrame.new(0, -partTouchedSizeYHalf, 0)).Position - pivot).Magnitude
local angle = (partTouched.Size.Y/part.Size.Y * height)/(part.Position - pivot).Magnitude
tween('Activation', part, newCFrame * CFrame.Angles(angle, 0, 0))
data.ActivationUpdated = true
end
end)
physicsConnections[hitboxInstance].TouchEnded = hitboxInstance.TouchEnded:Connect(function(partTouched : BasePart)
if not (grassData[partTouched]) or not (grassData[partTouched].IsEligible) then return end
if table.find(activeParts, partTouched) then
activeParts[table.find(activeParts, partTouched)] = nil
end
if partTouched:FindFirstChild('TouchedFloor') then
tween('Color', partTouched.TouchedFloor, Color3.new(0.5, 0.5, 0.5))
tween('Position', partTouched.TouchedFloor, partTouched.TouchedFloor.Position - Vector3.new(0, 10, 0))
wait(0.5)
partTouched.TouchedFloor:Destroy()
end
if grassData[partTouched].ActivationUpdated then
local newCFrame : CFrame = CFrame.new(partTouched.Position) * rotationCFrame
tween('Activation', partTouched, newCFrame)
grassData[partTouched].ActivationUpdated = false
end
end)
end
local function deactivateHitbox(hitboxInstance : BasePart)
if physicsConnections[hitboxInstance] then
physicsConnections[hitboxInstance].Touched:Disconnect()
physicsConnections[hitboxInstance].TouchEnded:Disconnect()
physicsConnections[hitboxInstance] = nil
end
end
local function handleHitboxEligibility(part : BasePart)
if not hitboxes[part] then
hitboxes[part] = {IsEligible = false, ActivationUpdated = false}
end
end
local eligibleParts : {BasePart} = CLS:GetTagged('tallGrass')
for _, eligiblePart in ipairs(eligibleParts) do
if eligiblePart:IsDescendantOf(workspace) and eligiblePart:IsA('BasePart') then
if not hitboxes[eligiblePart] then
hitboxes[eligiblePart] = {}
end
if not hitboxes[eligiblePart].IsEligible then
hitboxes[eligiblePart].IsEligible = true
activateHitbox(eligiblePart)
hitboxEligibilityChanged = true
end
end
end
for partTouched, _ in pairs(hitboxes) do
if partTouched:IsDescendantOf(workspace) and partTouched:IsA('BasePart') and partTouched ~= part then
if not table.find(eligibleParts, partTouched) then
hitboxes[partTouched].IsEligible = false
deactivateHitbox(partTouched)
hitboxEligibilityChanged = true
end
end
end
local function handleEligibility(part : BasePart)
if not grassData[part] then
grassData[part] = {Top = Vector3.new(), Pivot = Vector3.new(), IsEligible = false, ActivationUpdated = false}
end
local activationEnabled : boolean = (part.Position - camera.CFrame.Position).Magnitude <= activationRadius
if not grassData[part].IsEligible and activationEnabled then
grassData[part].IsEligible = true
hitboxEligibilityChanged = true
elseif grassData[part].IsEligible and not activationEnabled then
grassData[part].IsEligible = false
hitboxEligibilityChanged = true
end
end
local function updateGrassData()
local parts : {BasePart} = CLS:GetTagged('tallGrass')
for _, part in ipairs(parts) do
if part:IsDescendantOf(workspace) and part:IsA('BasePart') then
handleEligibility(part)
if grassData[part].IsEligible then
local position : Vector3 = part.Position
local size : Vector3 = part.Size
local top : Vector3 = Vector3.new(position.X, position.Y + (size.Y/root3), position.Z)
local pivot : Vector3 = position + ((top - position)/2)
grassData[part].Top = top
grassData[part].Pivot = pivot
end
end
end
end
local function handleActivation()
local currentCFrame : CFrame = camera.CFrame
local rotationAngle : number = (currentCFrame.Position - lastCFrame.Position).Y
for partTouched, data in pairs(grassData) do
if partTouched:IsDescendantOf(workspace) and partTouched:IsA('BasePart') and data.ActivationUpdated then
local newCFrame : CFrame = partTouched.CFrame * CFrame.Angles(0, math.rad(rotationAngle), 0)
tween('Activation', partTouched, newCFrame)
data.ActivationUpdated = false
end
end
lastCFrame = currentCFrame
end
local function main()
while RS:IsRunning() do
if timeCount >= timeInterval then
updateGrassData()
timeCount = 0
end
if updateTimeCount >= updateInterval then
handleActivation()
if hitboxEligibilityChanged then
handleHitboxEligibility()
hitboxEligibilityChanged = false
end
updateTimeCount = 0
updateCount = updateCount + 1
end
timeCount = timeCount + RS.Heartbeat:Wait()
updateTimeCount = updateTimeCount + RS.Heartbeat:Wait()
end
end
main()```