Interaction system broke, help needed!

Hello devforum, i have a repetitive issue now over my heavily modified interaction system. Basically around july i had a interaction module, i founded it unprofessional and outdated, so i tried “modernizing” the module, but while doing that something just broke it. I seriously need help with tracking the error/cause.

I tried comparing the 2 scripts by eye, and still no luck sadly.

broken/modernized script under here

local InteractingDistance = 5.5;
local CollectionService = game:GetService("CollectionService")
local RootParts = CollectionService:GetTagged("RootParts")

local Interactions = {}
Interactions.i = Interactions

local Interacting = false
local InteractingCooldown = false
local EndedInputTween = nil
local CooldownTime = .35

local FullBarSize = UDim2.new(1, 0,1, 0);
local EmptyBarSize = UDim2.new(0, 0,1, 0);

function Interactions.begin()
	local self = setmetatable({
		CurrentInteraction = nil;
		CurrentUIObject = nil;
		CurrentKey = nil;
		Holdable = false;
		InteractiveAttachments = workspace:FindFirstChild("InteractiveAttachments");
		Roots = {};
		UI = script.Parent.Parent:FindFirstChild("Move");
		Player = game:GetService('Players').LocalPlayer;
		Character =  game:GetService('Players').LocalPlayer.Character or game:GetService('Players').LocalPlayer.CharacterAdded:Wait();
	},Interactions)
	self.Roots = CollectionService:GetTagged("RootParts")
	CollectionService:GetInstanceAddedSignal("RootParts"):Connect(function(Root)
		self.Roots = CollectionService:GetTagged("RootParts")
		for i,v in pairs(self.Roots) do
			if (v == self.Character.HumanoidRootPart) then
				table.remove(self.Roots,i)
				print("Removing our root parts!")
			end
		end
	end)
	return self
end;

function Interactions:RayCastToAttach()
	local Params = RaycastParams.new()
	Params.FilterType = Enum.RaycastFilterType.Blacklist	
	Params.FilterDescendantsInstances = {self.CurrentInteraction}

	local raycastResult = Ray.new(self.CurrentInteraction.WorldPosition, (self.Character.PrimaryPart.Position - self.CurrentInteraction.WorldPosition).Unit*InteractingDistance, Params)
	local hit, position = workspace:FindPartOnRayWithIgnoreList(raycastResult, {self.CurrentInteraction})

	if (raycastResult) then
		if hit:IsDescendantOf(self.Character) then--nothing in the way detected	
			return true	

		elseif hit:IsDescendantOf(self.CurrentInteraction)	then--nothing in the way detected	
			return true		

		elseif hit.CanCollide == true then--something in the way detected
			return false			
		end
	end	

	return true
end;

function Interactions:HoldingEnded()
	self.CurrentKey = nil		
	Interacting = false	
	EndedInputTween:Cancel()
	EndedInputTween = nil
	self.CurrentUIObject:FindFirstChild("FillBar").Size = EmptyBarSize
end;

function Interactions:Clean()
self.CurrentUIObject = nil
self.CurrentKey = nil
self.CurrentInteraction = nil
	
if Interacting then	
self:HoldingEnded()	
end	
	
	for i,v in pairs(self.UI:GetChildren()) do
		if (v:IsA("Frame")) then
			v:Destroy()
		end
	end
end;

function Interactions:CheckIfHoldable()
	local interaction = self.CurrentInteraction

	if (interaction) then
		if interaction:IsA("Attachment") and interaction:IsDescendantOf(self.InteractiveAttachments) then else return end
		local Module = interaction:FindFirstChildWhichIsA("ModuleScript")
		if (Module) then
			Module = require(Module)
			for i,v in pairs(self.UI:GetChildren()) do
				if (v:IsA("Frame")) then
					for a,b in pairs(Module) do
						self.Holdable = b.Holdable   
					end;
				end
			end;
		end
	end
end;

function Interactions:InteractedEffect()
	local interaction = self.CurrentInteraction
	local CurrentFrame = self.CurrentUIObject	

	CurrentFrame:FindFirstChild("UIAspectRatioConstraint").AspectRatio = 1
	CurrentFrame:FindFirstChild("Background").BackgroundTransparency = 0
	CurrentFrame:FindFirstChild("Key").TextTransparency = 0
	CurrentFrame:FindFirstChild("FillBar").Size = EmptyBarSize

	local play1 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = UDim2.new(0, 0,1, 0)})	
	local play2 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {BackgroundTransparency = 1})	
	local play3 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Key"), TweenInfo.new(CooldownTime/2.5, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {TextTransparency = 1})

	play1:Play()	
	play2:Play()	
	play3:Play()	
	wait(CooldownTime/2)	
	play1:Cancel()	
	play2:Cancel()	
	play3:Cancel()	
	game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = UDim2.new(1, 0,1, 0)}):Play()	
	game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {BackgroundTransparency = 0.5}):Play()	
	game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Key"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {TextTransparency = 0}):Play()	
end;

function Interactions:Cooldown()
	Interacting = false	
	InteractingCooldown = true	
	self.CurrentUIObject:FindFirstChild("Background").BorderColor3 = Color3.new(0.12, 0.12, 0.12)	
	wait(CooldownTime)	
	Interacting = false	
	InteractingCooldown = false		
	self.CurrentUIObject:FindFirstChild("Background").BorderColor3 = Color3.new(0, 0, 0)		
end;

function Interactions:Input(key)
	if (key) then 
		local interaction = self.CurrentInteraction
		if (interaction) and not Interacting and not InteractingCooldown then
			if interaction:IsA("Attachment") and interaction:IsDescendantOf(self.InteractiveAttachments) then else return end 
			local Module = interaction:FindFirstChildWhichIsA("ModuleScript")
			if (Module) then
				Module = require(Module)
				for i,v in pairs(self.UI:GetChildren()) do
					if (v:IsA("Frame")) then
						for a,b in pairs(Module) do
							if (v.Key.Text == tostring(b.KeyCode):sub(14,123123)) then
								if (key == b.KeyCode) then
									self.CurrentKey = b.KeyCode 
									if b.Holdable == true then
										EndedInputTween = game:GetService("TweenService"):Create(self.CurrentUIObject:FindFirstChild("FillBar"), TweenInfo.new(b.HoldingTime, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = FullBarSize})		
										EndedInputTween:Play()	

										Interacting = true	
									else									
										b.Function()
										self:InteractedEffect()
										self:CheckIfHoldable()
										self:Cooldown()
									end	
								end
							end
						end;
					end
				end;
			end
		end
	end
end;

function Interactions:InputEnded(key)
	if (key) then
		local interaction = self.CurrentInteraction
		if (interaction) and not InteractingCooldown then
			if interaction:IsA("Attachment") and interaction:IsDescendantOf(self.InteractiveAttachments) then else return end 		
			local Module = interaction:FindFirstChildWhichIsA("ModuleScript")
			if (Module) then
				Module = require(Module)
				for i,v in pairs(self.UI:GetChildren()) do
					if (v:IsA("Frame")) then
						for a,b in pairs(Module) do
							if (v.Key.Text == tostring(b.KeyCode):sub(14,123123)) then
								if (key == self.CurrentKey) and Interacting then
									self:HoldingEnded()
								else									
								end
							end
						end;
					end
				end;
			end	
		end
	end
end;

function Interactions:SetupCurrentInteraction()
	local interaction = self.CurrentInteraction
	self.CurrentUIObject = nil
	self:CheckIfHoldable()

	if interaction:IsA("Attachment") and interaction:IsDescendantOf(self.InteractiveAttachments) then	

	local Module = interaction:FindFirstChildWhichIsA("ModuleScript")
	if (Module) then
		Module = require(Module)
		for i,v in pairs(Module) do
			local tmp = script:FindFirstChild("template"):Clone()
			self.CurrentUIObject = tmp
			tmp.Parent = self.UI
			tmp.Key.TextColor3 = v.KeyColor
			tmp.Key.Text = tostring(v.KeyCode):sub(14,123123)
		end;
	end
	else return end	
end;

function Interactions:Update()
if (self.Character) and (self.Character):FindFirstChild("Humanoid").Health >0 then	
if (self.CurrentInteraction) and (self.CurrentUIObject) then
			if self.CurrentInteraction:IsA("Attachment") and self.CurrentInteraction:IsDescendantOf(self.InteractiveAttachments) then
			if (self.Character):FindFirstChild("Humanoid").Health <=0 then
			self:Clean()	
			return end


			local camera = workspace.CurrentCamera
			local WSP,InScreen = camera:WorldToScreenPoint(self.CurrentInteraction.WorldPosition)
			if (InScreen) then
				if self.CurrentUIObject:FindFirstChild("FillBar").Size == FullBarSize and Interacting then
					local interaction = self.CurrentInteraction

					if (interaction) then
						if interaction:IsA("BasePart") or interaction:IsA("MeshPart") or interaction:IsA("TrussPart") or interaction:IsA("WedgePart") or interaction:IsA("CornerWedgePart") or interaction:IsA("OnionOperation") or interaction:IsA("NegateOperation") then			
							if interaction:IsA("Attachment") and interaction:IsDescendantOf(self.InteractiveAttachments) then	
							local Module = interaction:FindFirstChildWhichIsA("ModuleScript")
							if (Module) then
								Module = require(Module)
								for i,v in pairs(self.UI:GetChildren()) do
									if (v:IsA("Frame")) then
										for a,b in pairs(Module) do
											b.Function()--makes the function function duh 
											EndedInputTween:Cancel()
											EndedInputTween = nil
											self.CurrentUIObject:FindFirstChild("FillBar").Size = EmptyBarSize				
										end;
									end
								end;
							end
							else return end	
						end	
					end
				end		
				self.CurrentKey = nil		
				Interacting = false		
				self:InteractedEffect()
				self:CheckIfHoldable()
				self:Cooldown()		

			elseif not (InScreen) then	
				self:Clean()	
			end		

			self:RayCastToAttach()
			if self:RayCastToAttach() then
				self.UI.Visible = true
				self.UI.Position = UDim2.new(0,WSP.X,0,WSP.Y) + UDim2.new(-0.015,0,-0.005,0)
			else
				self:Clean()	
				--self.CurrentUIObject = nil
			end	
		else
		--self:Clean()
		--self.CurrentUIObject = nil	
	for i,v in pairs({table.unpack(self.InteractiveAttachments:GetDescendants()),table.unpack(self.Roots)}) do
		if v:IsA("BasePart") or v:IsA("MeshPart") or v:IsA("TrussPart") or v:IsA("WedgePart") or v:IsA("CornerWedgePart") or v:IsA("OnionOperation") or v:IsA("NegateOperation") then
			if v:IsA("Attachment") and v:IsDescendantOf(self.InteractiveAttachments) then else return end
				if (self.Player:DistanceFromCharacter(v.WorldPosition) <= InteractingDistance) then else return end	
					if (v:FindFirstChildWhichIsA("ModuleScript") and v ~= self.CurrentInteraction) then
						self:Clean()
						self.CurrentInteraction = v
						self:SetupCurrentInteraction()
					end
				elseif (self.Player:DistanceFromCharacter(self.CurrentInteraction.WorldPosition) > InteractingDistance) then		
					self:Clean()			
	            end			
	        end	
	end	
end	
else 	
if (self.CurrentInteraction) then
self:Clean()			
end				
return end				
end;

return Interactions

old script under here

local Player = game:GetService('Players').LocalPlayer
local Character =  game:GetService('Players').LocalPlayer.Character or  game:GetService('Players').LocalPlayer.CharacterAdded:Wait()

local InteractingDistance = 6;
local CollectionService = game:GetService("CollectionService")
local RootParts = CollectionService:GetTagged("RootParts")

local Interactions = {}
Interactions.__index = Interactions

local Interacting = false
local InteractingCooldown = false
local EndedInputTween = nil
local CooldownTime = .35

local FullBarSize = UDim2.new(1, 0,1, 0)
local EmptyBarSize = UDim2.new(0, 0,1, 0)	
	
function Interactions.begin()
	local self = setmetatable({
		CurrentInteraction = nil;
		CurrentUIObject = nil;
		CurrentKey = nil;
		Holdable = false;
		InteractiveAttachments = workspace:FindFirstChild("InteractiveAttachments"):GetChildren();
		Roots = {};
		UI = script.Parent.Parent:FindFirstChild("Move");
		Player = game:GetService('Players').LocalPlayer;
		Character =  game:GetService('Players').LocalPlayer.Character or  game:GetService('Players').LocalPlayer.CharacterAdded:Wait();
	    },Interactions)
	self.Roots = CollectionService:GetTagged("RootParts")
	CollectionService:GetInstanceAddedSignal("RootParts"):Connect(function(Root)
		self.Roots = CollectionService:GetTagged("RootParts")
		for i,v in pairs(self.Roots) do
			if (v == self.Character.HumanoidRootPart) then
				table.remove(self.Roots,i)
				print("Removing our root parts!")
			end
		end
	end)
	return self
end;

function Interactions:RayCastToAttach()
	--local Selectedcharacter	= nil
	--for _,player in ipairs(game.Players:GetPlayers()) do
	--	Selectedcharacter = player.Character
	--end	

	local Params = RaycastParams.new()
	Params.FilterType = Enum.RaycastFilterType.Blacklist	
	Params.FilterDescendantsInstances = {Character}
	
	local origin = Character.PrimaryPart.Position
	local direction = (self.CurrentInteraction.WorldPosition - origin).Unit
	
	local raycastResult = workspace:Raycast(Character.PrimaryPart.Position, direction*InteractingDistance, Params)
	
	if raycastResult then
		local hitPart = raycastResult.Instance
		
		if hitPart.CanCollide == true then	
		if hitPart == self.CurrentInteraction.Parent then--detected the attachment's property, returning as true. 	
		return true			
		else--something in the way detected		
		return false	
		end			
		else--nothing in the way detected	
		return true	
		end
	else--nothing in the way detected	
	return true	
	end
end;

function Interactions:Clean()
	for i,v in pairs(self.UI:GetChildren()) do
		if (v:IsA("Frame")) then
			v:Destroy()
			self.CurrentUIObject = nil
			self.CurrentKey = nil
		end
	end
end

function Interactions:CheckIfHoldable()
local interaction = self.CurrentInteraction
	
   if (interaction) then
	   if (interaction.ClassName == "Attachment") then else return end		
		local Module = interaction:FindFirstChild('Interaction')
		if (Module) then
			Module = require(Module)
			for i,v in pairs(self.UI:GetChildren()) do
				if (v:IsA("Frame")) then
					for a,b in pairs(Module) do
                    self.Holdable = b.Holdable   
					end;
				end
			end;
		end
	end
end

function Interactions:InteractedEffect()
local interaction = self.CurrentInteraction
local CurrentFrame = self.CurrentUIObject	
	
CurrentFrame:FindFirstChild("UIAspectRatioConstraint").AspectRatio = 1
CurrentFrame:FindFirstChild("Background").BackgroundTransparency = .0
CurrentFrame:FindFirstChild("Key").TextTransparency = 0
CurrentFrame:FindFirstChild("FillBar").Size = EmptyBarSize
	
local play1 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = UDim2.new(0, 0,1, 0)})	
local play2 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {BackgroundTransparency = 1})	
local play3 = game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Key"), TweenInfo.new(CooldownTime/2.5, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {TextTransparency = 1})
	
play1:Play()	
play2:Play()	
play3:Play()	
wait(CooldownTime/2)	
play1:Cancel()	
play2:Cancel()	
play3:Cancel()	
game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = UDim2.new(1, 0,1, 0)}):Play()	
game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Background"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {BackgroundTransparency = 0.5}):Play()	
game:GetService("TweenService"):Create(CurrentFrame:FindFirstChild("Key"), TweenInfo.new(CooldownTime/2, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {TextTransparency = 0}):Play()	
end;

function Interactions:Cooldown()
Interacting = false	
InteractingCooldown = true	
self.CurrentUIObject:FindFirstChild("Background").BorderColor3 = Color3.new(0.12, 0.12, 0.12)	
wait(CooldownTime)	
Interacting = false	
InteractingCooldown = false		
self.CurrentUIObject:FindFirstChild("Background").BorderColor3 = Color3.new(0, 0, 0)		
end

function Interactions:Input(key)
	if (key) then 
		local interaction = self.CurrentInteraction
		if (interaction) and not Interacting and not InteractingCooldown then
		  if (interaction.ClassName == "Attachment") then else return end		
			local Module = interaction:FindFirstChild('Interaction')
			if (Module) then
				Module = require(Module)
				for i,v in pairs(self.UI:GetChildren()) do
					if (v:IsA("Frame")) then
						for a,b in pairs(Module) do
							if (v.Key.Text == tostring(b.KeyCode):sub(14,123123)) then
								if (key == b.KeyCode) then
									self.CurrentKey = b.KeyCode 
									if b.Holdable == true then
									EndedInputTween = game:GetService("TweenService"):Create(self.CurrentUIObject:FindFirstChild("FillBar"), TweenInfo.new(b.HoldingTime, Enum.EasingStyle.Linear, Enum.EasingDirection.Out), {Size = FullBarSize})		
									EndedInputTween:Play()	
										
									Interacting = true	
									else									
									b.Function()
									self:InteractedEffect()
									self:CheckIfHoldable()
									self:Cooldown()
									end	
								end
							end
						end;
					end
				end;
			end
		end
	end
end

function Interactions:HoldingEnded()
self.CurrentKey = nil		
Interacting = false	
EndedInputTween:Cancel()
EndedInputTween = nil
self.CurrentUIObject:FindFirstChild("FillBar").Size = EmptyBarSize
end

function Interactions:InputEnded(key)
	if (key) then
		local interaction = self.CurrentInteraction
		if (interaction) and not InteractingCooldown then
		  if (interaction.ClassName == "Attachment") then else return end		
			local Module = interaction:FindFirstChild('Interaction')
			if (Module) then
				Module = require(Module)
				for i,v in pairs(self.UI:GetChildren()) do
					if (v:IsA("Frame")) then
						for a,b in pairs(Module) do
							if (v.Key.Text == tostring(b.KeyCode):sub(14,123123)) then
								if (key == self.CurrentKey) and Interacting then
									self:HoldingEnded()
									else									
								end
							end
						end;
					end
				end;
			end
		end
	end
end;

function Interactions:SetupCurrentInteraction()
	local interaction = self.CurrentInteraction
	self:Clean()
	self.CurrentUIObject = nil
	self:CheckIfHoldable()
	
	if (interaction.ClassName == "Attachment") then else return end		
	
	local Module = interaction:FindFirstChild('Interaction')
	if (Module) then
		Module = require(Module)
		for i,v in pairs(Module) do
			local tmp = script:FindFirstChild("template"):Clone()
			self.CurrentUIObject = tmp
			tmp.Parent = self.UI
			tmp.Key.TextColor3 = v.KeyColor
			tmp.Key.Text = tostring(v.KeyCode):sub(14,123123)
		end;
	end
end;

function Interactions:Update()
	if (self.Character) then
		if (self.CurrentInteraction) then
			if (self.CurrentInteraction.ClassName == "Attachment") then else return end		
			local camera = workspace.CurrentCamera
			local WSP,InScreen = camera:WorldToScreenPoint(self.CurrentInteraction.WorldPosition)
			if (InScreen) then
			if self.CurrentUIObject:FindFirstChild("FillBar").Size == FullBarSize and Interacting then
			local interaction = self.CurrentInteraction

			if (interaction) then
			if (interaction.ClassName == "Attachment") then else return end		
				local Module = interaction:FindFirstChild('Interaction')
					if (Module) then
							Module = require(Module)
						for i,v in pairs(self.UI:GetChildren()) do
							if (v:IsA("Frame")) then
							for a,b in pairs(Module) do
							b.Function()--makes the function function duh 
							EndedInputTween:Cancel()
							EndedInputTween = nil
                            self.CurrentUIObject:FindFirstChild("FillBar").Size = EmptyBarSize				
							end;
						end
					end;
				end
			end		
			self.CurrentKey = nil		
			Interacting = false		
			self:InteractedEffect()
			self:CheckIfHoldable()
			self:Cooldown()		
			end	
				
				self:RayCastToAttach()
				if self:RayCastToAttach() then
				self.UI.Visible = true
				self.UI.Position = UDim2.new(0,WSP.X,0,WSP.Y) + UDim2.new(-0.015,0,-0.005,0)
			   else
				self.UI.Visible = false
				--self.CurrentUIObject = nil
			    end
			end	
		else
			self.UI.Visible = false
			--self.CurrentUIObject = nil
		end
		for i,v in pairs({table.unpack(self.InteractiveAttachments),table.unpack(self.Roots)}) do
			if v:FindFirstChildWhichIsA("Attachment") then else return end
			if (self.Player:DistanceFromCharacter(v:FindFirstChildWhichIsA("Attachment").WorldPosition) <= InteractingDistance) then
				if (v:FindFirstChildWhichIsA("Attachment") ~= self.CurrentInteraction) then
					self.CurrentInteraction = v:FindFirstChildWhichIsA("Attachment")
					self:SetupCurrentInteraction()
					return
				end
				return
			elseif (self.Player:DistanceFromCharacter(v:FindFirstChildWhichIsA("Attachment").WorldPosition) > InteractingDistance) then		
			if Interacting then	
			self:HoldingEnded()	
			end
			self.CurrentInteraction = nil
			--self.CurrentUIObject = nil
			end	
		end
	end
end;

return Interactions

Somebody willing to read the scripts and help me find where it went wrong, please address me this problem, it has gone for far too long.

One thing I noticed with a quick pass:
You renamed Interactions.__index to Interactions.i on line 6. __index is a special name reserved for metatables, so renaming this will definitely break functionality where self is trying to call a function on itself. To fix this, change the name back to __index (note the double underscore)

Overall, your post is difficult to answer because we have no context for what this script does, how we can test it, and how to reproduce any issues on our computers. You also haven’t included a specific error or description of any problem, so overall, this post is too unspecific for anyone to answer with confidence.

2 Likes

Sorry for not being very specific, basically there’s a localscript and the module is parented by the localscript, the localscript calls the .begin() function of the modulescript. Although I’m in school currently, I’ll see at home if this solution works. If so, I’ll mark it as a solution.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.