.Touched triggering before part is touched

Hello I’m currently having a problem with Touched being fired before the part actually touches something. I have a projectile script that generates a ball above the player’s character and fires it to a desired direction, currently I’ve removed the body velocity and made it so once it’s fired it will only fall to the ground. The thing is I have two parts inside of the ball, one part is another ball that is placed inside so the ball looks better, the other part is a normal part that is placed in the middle of the ball, both parts are welded to the main ball. Inside of the projectile script I have a .Touched event listening if the part placed in the middle is touched and if it’s touched it would anchor the main ball, the thing is the main ball its getting anchored before the part touches anything. A interesting thing is that this happens only in the client, if I view it from the server it works properly.

Client:
Client

Server:
Server

Here is the entire script.
Any help would be appreciated.

local rs = game:GetService("ReplicatedStorage")
local ts = game:GetService("TweenService")
local revent = rs:WaitForChild("Genki")
local RunService = game:GetService("RunService")
local fireready = false
local animationstatuswanted = nil
local animationnum = nil
local animationfinishedreceived = nil
local alreadycrashed = nil

revent.OnServerEvent:Connect(function(plr, mouse, active, animationfinished)
	local Humanoid = plr.Character.Humanoid
	local Character = plr.Character
	if Humanoid.Health > 0 then 
		if mouse ~= nil and active ~= nil then
			print("numb1 works")
			if active == false then
				
				-- Principal Vars --
				local genkiFolder = Instance.new("Folder", workspace)
				genkiFolder.Name = plr.Name.."Genki"
				local genkiOut = script.GenkiOut:Clone()
				genkiOut.Parent = genkiFolder

					
				local genkiIn = genkiOut.Genki
				local glowParticle = genkiOut.Attachment.Glow
				local recollectParticle = genkiIn.Recollect
				local righthand = Character.RightHand
				local lefthand = Character.LeftHand
				-- Inmobilize Player --
				Humanoid.WalkSpeed = 0
				Humanoid.JumpPower = 0
				
			    -- Pre Position --
				genkiOut.CFrame = righthand.CFrame:Lerp(lefthand.CFrame, 0.5)
				genkiOut.CFrame = genkiOut.CFrame + Vector3.new(0,7,0)
			
				
				-- Growth Animation --
				animationnum = {1,2}
				animationstatuswanted = {"start", "loop"}
				revent:FireClient(plr, animationnum, animationstatuswanted)	
				repeat wait() until animationfinishedreceived == true
				animationfinishedreceived = false
				
				-- Genki Position and Welding --
				
				local weld = Instance.new("WeldConstraint", righthand)
				weld.Part0 = righthand
				genkiOut.Anchored = false
				weld.Part1 = genkiOut
				genkiOut:SetNetworkOwner(nil)
				genkiIn:SetNetworkOwner(nil)
				genkiOut.Transparency = 0.8
				genkiIn.Transparency = 0
				
			
			
				-- Genki Growth -- 
				for i, v in pairs(genkiFolder:GetDescendants()) do
					if v:IsA("Part") then 
						local growthgoal = {Size = Vector3.new(34,34,34), Position = v.Position + Vector3.new(0,15,0)}
						local growthinfo = TweenInfo.new(5)
						if v.Name == "GenkiOut" then
							growthgoal = {Size = Vector3.new(38,38,38), Position = v.Position + Vector3.new(0,15,0)}
						end
						local growthtween = ts:Create(v, growthinfo, growthgoal)
						growthtween:Play()
					elseif v:IsA("ParticleEmitter") then
						if v.Name == "Recollect" then
							v.Enabled = true
						else
							genkiOut:GetPropertyChangedSignal("Size"):Connect(function()		
								if genkiOut.Size == Vector3.new(38,38,38) then
									v.Enabled = true
									fireready = true
								end
							end)
		
						end
					end
				end	
		
			elseif active == true then
				print("numb2 works")
				repeat wait() until fireready == true
				alreadycrashed = false
				
				-- Stopping last animations --
				animationnum = 2
				animationstatuswanted = "stop"
				revent:FireClient(plr, animationnum, animationstatuswanted)
				print("sent")
				
				-- Recuperando Variables --
				local genkiFolder = workspace:FindFirstChild(plr.Name.."Genki")
				local genkiOut = genkiFolder:FindFirstChild("GenkiOut")
				local genkiIn = genkiOut:FindFirstChild("Genki")
				local weld = Character.RightHand:FindFirstChild("WeldConstraint")
				local recollectparticle = genkiIn:FindFirstChild("Recollect")
				local glowparticle = genkiOut.Attachment:FindFirstChild("Glow")
				local firstWave = genkiOut:FindFirstChild("FirstWave")
				local midWave = genkiOut:FindFirstChild("MidWave")
				local lastWave = genkiOut:FindFirstChild("FinalWave")
				
				-- Throw Animation --
				animationnum = {3,4}
				animationstatuswanted = "start"
				revent:FireClient(plr, animationnum, animationstatuswanted)
				repeat wait() until animationfinishedreceived == true
				print("fire xd")
				
				-- Throw Genki --
				weld:Destroy()

				--[[
				local bodyvelo = Instance.new("BodyVelocity", genkiOut)
				bodyvelo.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
				bodyvelo.P = 10000
				bodyvelo.Velocity = CFrame.new(genkiOut.Position, mouse).LookVector*100
				]]--
				
				-- Touched Event --
				local explosionPart = Instance.new("Part", genkiOut)
				explosionPart.CanCollide = false
				explosionPart.Shape = Enum.PartType.Block
				explosionPart.Size = Vector3.new(50,0.1,5)
				explosionPart.Material = Enum.Material.Neon
				explosionPart.Color = Color3.new(0.333333, 1, 1)
				explosionPart.CFrame = genkiOut.CFrame + Vector3.new(0,5,0)
				explosionPart.Transparency = 0
				explosionPart.Name = "ExplosionPart"
				local exploWeld = Instance.new("WeldConstraint", genkiOut)
				exploWeld.Part0 = genkiOut
				exploWeld.Part1 = explosionPart
				
				
				
				RunService.Heartbeat:Wait()
				explosionPart.Anchored = false
				explosionPart:SetNetworkOwner(nil)
				
				genkiOut.Touched:Connect(function(Hit)		
					if Hit:IsA("Part") or Hit:IsA("MeshPart") then
						if not Hit:IsDescendantOf(genkiFolder) and not Hit:IsDescendantOf(Character) then
							local HitHum = Hit.Parent:FindFirstChild("Humanoid")
							if HitHum then
								if not Hit.Parent:FindFirstChild("Damaging") then
									local damaging = Instance.new("BoolValue", Hit.Parent)
									damaging.Name = "Damaging"
									HitHum:TakeDamage(25)
									game.Debris:AddItem(damaging, 2)
								end
							end
						end
					end
				end)
				
				explosionPart.Touched:Connect(function(Hit)
					if Hit:IsA("Part") or Hit:IsA("MeshPart") then
						if not Hit:IsDescendantOf(genkiFolder) and not Hit:IsDescendantOf(Character) then
							-- bodyvelo:Destroy()
							if explosionPart:GetNetworkOwner() == nil and genkiOut:GetNetworkOwner() == nil then
								print("NetworkOwnerIsServer")
							end
							genkiOut.Anchored = true
							local HitHum = Hit.Parent:FindFirstChild("Humanoid")
							if HitHum then
								if not Hit.Parent:FindFirstChild("AlreadyHit") then
									local alreadyHit = Instance.new("BoolValue", Hit.Parent)
									alreadyHit.Name = "AlreadyHit"
									HitHum:TakeDamage(50)
									game.Debris:AddItem(alreadyHit, 20)
								end
							elseif HitHum == nil and alreadycrashed == false then
								alreadycrashed = true
								
								-- Final Effects --
								
								local bouncecount = 0
								local wavecount = 0
								local function effects(v, case)
									if case == "part" then
										local inCasePart = coroutine.create(function()
											repeat
												local bouncegoal = {Size = v.Size + Vector3.new(5,5,5)}
												local info = TweenInfo.new(1)
												local bouncetween = ts:Create(v, info, bouncegoal)
												bouncetween:Play()
												bouncetween.Completed:Connect(function()
													bouncegoal = {Size = v.Size - Vector3.new(5,5,5)}
													bouncetween = ts:Create(v, info, bouncegoal)
													bouncetween:Play()
													bouncecount = bouncecount + 1
												end)
												wait(2)
											until bouncecount == 8
										end)
										coroutine.resume(inCasePart)
									elseif case == "meshpart" then
										local inCaseMesh = coroutine.create(function()
											repeat
												if v.Name == "FirstWave" then
													local firstClone = v:Clone()
													firstClone.Parent = firstWave
													firstClone.Position = explosionPart.Position + Vector3.new(0,1,0)
													local sizegoal = {Size = Vector3.new(50,10,50), Orientation = Vector3.new(0,360,0)}
													local transgoal = {Transparency = 1}
													local info = TweenInfo.new(1)
													local info2 = TweenInfo.new(4)
													local sizetween = ts:Create(firstClone, info, sizegoal)
													local transtween = ts:Create(firstClone, info2, transgoal)
													sizetween:Play()
													transtween:Play()
													wavecount = wavecount + 0.5
												elseif v.Name == "MidWave" then
													local midClone = v:Clone()
													midClone.Parent = midWave
													midClone.Position = explosionPart.Position 
													midClone.Size = Vector3.new(55,2.111,55)
													local info = TweenInfo.new(2)
													local transinfo = TweenInfo.new(4)
													local goal = {Size = midClone.Size - Vector3.new(20,0,20), Orientation = Vector3.new(0,360,0), Position = midClone.Position + Vector3.new(0,15,0)}
													local transgoal = {Transparency = 1}
													local tween = ts:Create(midClone, info, goal)
													local transtween = ts:Create(midClone, info, transgoal)
													tween:Play()
													transtween:Play()
													wavecount = wavecount + 0.5
												elseif v.Name == "LastWave" and wavecount == 7 then
													local lastClone = v:Clone()
													lastClone.Parent = lastWave
													lastClone.CFrame = explosionPart.CFrame
													local info = TweenInfo.new(4)
													local goal = {Size = lastClone.Size + Vector3.new(60,0,60), Transparency = 1}
													local tween = ts:Create(lastClone, info, goal)
													tween:Play()
													wavecount = wavecount + 0.5
												end
												wait(2)
											until wavecount == 8.5
										end)
										coroutine.resume(inCaseMesh)
									end
								end
								
								
								
					
								for i, v in pairs(genkiFolder:GetDescendants()) do
									if v:IsA("Part") then
										local case = "part"
										--effects(v, case)
									elseif v:IsA("MeshPart") then
										local case = "meshpart"
										--effects(v, case)
									elseif v:IsA("ParticleEmitter") then
										print("effects")
									end
								end
								
							end
						end
					end
				end)
				
				
				
				
			end
		elseif animationfinished ~= nil then
			if animationfinished == true then
				animationfinishedreceived = true
			end
		end
	end
end)

There is the script, it’s not completed but I wanted to fix this first.

This probably has to do with the client server latency. One way you can fix this is by setting the projectile’s network ownership to nil.

2 Likes

I’ll try that but I have a few questions. I didn’t know about network ownership until now, I searched it and understood the basics, thanks for that. But what is the difference of setting the network ownership to nil and setting it to the server? And do I need to set this on the welded parts also or only on the main part?
Sorry if it sounds stupid…

I understand how you’re really confused about this I was too at first when dealing with network ownership. Setting the network ownership to nil means that no players are taking over priority of the parts physical simulation which basically mean that the server is in charge here. So setting the network owner to nil makes the server the network owner. As for welded parts, when you weld two or more parts they become a rig. In a rig the network ownership is inherited by the primary part that is unanchored.

1 Like

It still doesn’t work :¨(, I still don’t understand what the problem is. Here is a script of how I’m changing the network ownership:

				local weld = Instance.new("WeldConstraint", righthand)
				weld.Part0 = righthand
				genkiOut.Anchored = false
				genkiOut:SetNetworkOwner(nil)
				weld.Part1 = genkiOut
				genkiOut.Transparency = 0.8
				genkiIn.Transparency = 0

Do I have to set the right hand network ownership to nil??
Edit: The thing is first the main part is welded to the player’s right hand, then the main part and the righthand’s weld is destroyed and the middle part is welded to the main part.

So you’re setting the network ownership after you unweld it from the right arm, right?

No, I set the network ownership when I welded the part to the right arm as you can see in the script above, I tried to set the network ownership after I destroyed the weld but It will still not work:

-- Throw Genki --
				weld:Destroy()
				genkiOut:SetNetworkOwner(nil)

So now the main part is unanchored and not welded to any other part besides the middle part when you set the network ownership?

Oh wait sorry I was thinking that welds work like Motor6Ds in the sense that they inherit the network owner from the root part but if two parts are together and one is not defined as a root part then there isn’t really an assembly so you want to change the network owner of all the parts in your projectile to nil.

Here is what I did.
-The white ball part is already welded from the beginning to the main part
-I set the main part anchor to false and the main part is welded to the right arm.
-The right arm and main part weld is destroyed.
-I set the network ownership of the main part to nil.
-I instance a new part (middle part) position it and weld it to the main part.
-I listen for the .Touched in the middle part.

How I instanced the new part:

				local explosionPart = Instance.new("Part", genkiOut)
				explosionPart.Anchored = true
				explosionPart.CanCollide = false
				explosionPart.Shape = Enum.PartType.Block
				explosionPart.Size = Vector3.new(50,0.1,5)
				explosionPart.Material = Enum.Material.Neon
				explosionPart.Color = Color3.new(0.333333, 1, 1)
				explosionPart.CFrame = genkiOut.CFrame + Vector3.new(0,5,0)
				explosionPart.Transparency = 0
				explosionPart.Name = "ExplosionPart"
				local exploWeld = Instance.new("WeldConstraint", genkiOut)
				exploWeld.Part0 = genkiOut
				explosionPart.Anchored = false
				exploWeld.Part1 = explosionPart

No worries ! I’ll try it right now.
Edit: That also doesn’t work :¨(
I also tried removing the decoration part (white ball) and it’s weld but it still won’t work.

What if you have the script wait for one heartbeat before connecting the .touched event to a function so it gives the server time to establish a connection with clients and their physical simulations? You can do this with:

local RunService = game:GetService("RunService")

RunService.Heartbeat:Wait()
--then unanchor your parts and establish the touched event with your function

You mean like this?

				RunService.Heartbeat:Wait()
				explosionPart.Anchored = false
				explosionPart:SetNetworkOwner(nil)
				
				explosionPart.Touched:Connect(function(Hit)	

If it’s like that it didn’t work either. But if the network ownership is set to the server it’s supposed to show the exact same thing of what’s happening in the server right?

Well yes and no. The server is suppose to replicate the same to all clients, but it can depend on the users’ connection speed to the game. If all these suggestion didn’t work then I’m willing to bet that this is an error with studio or the engine in general. Did you try playing the game on an actual server to see if the error persists?

Couldn’t you just set up logic statements to detect who is touching it before doing all of that explosion effects?

Yes I tried it but it doesn’t work either. I don’t think is a error with the studio, I think it’s just my bad code, anyways I could share the entire script but it’s pretty large.

Yeah share the script it might be something to do with the order it runs in.

No because then it wouldn’t be working right on the server at all like he says it does.

You can even pm me if you don’t want the script to be public.

I set up Ifs in the Touched event:

explosionPart.Touched:Connect(function(Hit) -- ExplosionPart is the part in the middle.
					if Hit:IsA("Part") or Hit:IsA("MeshPart") then
						if not Hit:IsDescendantOf(genkiFolder) and not Hit:IsDescendantOf(Character) then -- genkiFolder is the folder where the parts are stored at.
                        -- do the rest --

Is this what you meant?

1 Like