Zipline jumping problems

Heyo Devforum! Recently, I have been scripting my own zipline from scratch, and I have successfully done it, but I have trouble with one problem. I want it so that my player can jump off of the zipline when he/she is on the zipline and jumps. I tried using humanoid.Jumping to see whether the player has jumped on the zipline, but it never works, and it only detects it once the player is off the zipline and jumping on the ground. Here is my script:

repeat wait() until game.Workspace:WaitForChild("Tower of Troubling Tutorials")
local ziplines = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines:GetChildren()

local tweenservice = game:GetService("TweenService")

for i, zipline in pairs(ziplines) do
	local isonzip = false

	local line = zipline.Line
	local finish = zipline.End
	local start = zipline.Start
	local slider = script.Slider
	local animation = script.ZiplineHold

	start.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			if not isonzip then
				isonzip = true
				local character = hit.Parent
				local humanoid = hit.Parent.Humanoid
				local sliderclone = slider:Clone()
				sliderclone.Parent = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines
				sliderclone.PrimaryPart.Position = start.Position
				local sliderpart = sliderclone.SliderPart
				local movingsliderpart = sliderclone.Part
				local weld = Instance.new("Weld")
				weld.Part0 = character.Head
				weld.Part1 = sliderpart
				weld.Parent = sliderpart
				sliderpart.CFrame = character.Head.CFrame
				local tweeninfo = TweenInfo.new(2)
				local goal = {}
				goal.CFrame = finish.CFrame
				local tween = tweenservice:Create(movingsliderpart, tweeninfo, goal)
				tween:Play()
				local loadanimation = humanoid:LoadAnimation(animation)
				loadanimation:Play()
				humanoid.Jumping:Connect(function()
					print("YEs")
					weld:Destroy()
					loadanimation:Stop()
					sliderclone:Destroy()
					isonzip = false
				end)
				wait(2)
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				isonzip = false
			end
		end
	end)
end

If you have any trouble understanding anything of my code, I will be happy to explain. Thank you!

Instead of asking the Humanoid whether the player jumped, we can go straight to the source of how players move. If you run your game, you’ll see PlayerModule under StarterPlayerScripts.

image

The PlayerModule is the code responsible for making your character and camera move. We can ask it instead whether the player is trying to jump. You might try something like this.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local Player = Players.LocalPlayer
local PlayerModule = require(Player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))
local Controls = PlayerModule:GetControls()

-- somewhere later in your zipline function
while not Controls:GetActiveController():GetIsJumping() do
	RunService.Heartbeat:Wait()
	print("waiting for jump")
end

print("player jumped")

The downside to this is that the control module doesn’t fire an event when the player jumps like Humanoid does, so you’re stuck busy waiting in a while loop.

1 Like

So AstroCode. I tried doing this and implemented it into my code, but I get an error: 22:15:05.164 - Players.HonestJar.PlayerScripts.LocalStuff.LocalZiplines:43: attempt to call a nil value

Here is the script:

repeat wait() until game.Workspace:WaitForChild("Tower of Troubling Tutorials")
local ziplines = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines:GetChildren()

local tweenservice = game:GetService("TweenService")
local runservice = game:GetService("RunService")

local player = game.Players.LocalPlayer
local playermodule = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))
local controls = playermodule:GetControls()

for i, zipline in pairs(ziplines) do
	local isonzip = false

	local line = zipline.Line
	local finish = zipline.End
	local start = zipline.Start
	local slider = script.Slider
	local animation = script.ZiplineHold

	start.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			if not isonzip then
				isonzip = true
				local character = hit.Parent
				local humanoid = hit.Parent.Humanoid
				local sliderclone = slider:Clone()
				sliderclone.Parent = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines
				sliderclone.PrimaryPart.Position = start.Position
				local sliderpart = sliderclone.SliderPart
				local movingsliderpart = sliderclone.Part
				local weld = Instance.new("Weld")
				weld.Part0 = character.Head
				weld.Part1 = sliderpart
				weld.Parent = sliderpart
				sliderpart.CFrame = character.Head.CFrame
				local tweeninfo = TweenInfo.new(2)
				local goal = {}
				goal.CFrame = finish.CFrame
				local tween = tweenservice:Create(movingsliderpart, tweeninfo, goal)
				tween:Play()
				local loadanimation = humanoid:LoadAnimation(animation)
				loadanimation:Play()
				while not controls:GetActivateController():GetIsJumping() do
					runservice.HeartBeat:Wait()
					print("Wait")
				end
				print("Jumped")
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				wait(2)
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				isonzip = false
			end
		end
	end)
end

You misspelled GetActiveController as GetActivateController.

EDIT: You also misspelled Heartbeat as HeartBeat.

1 Like

Hello AstroCode! After fixing everything, it works now so I must thank you on that, but now when the player DOESN’T jump, the weld and tween never destroy and stop. Did I place in the code block wrong?

Script:

repeat wait() until game.Workspace:WaitForChild("Tower of Troubling Tutorials")
local ziplines = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines:GetChildren()

local tweenservice = game:GetService("TweenService")
local runservice = game:GetService("RunService")

local player = game.Players.LocalPlayer
local playermodule = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))
local controls = playermodule:GetControls()

for i, zipline in pairs(ziplines) do
	local isonzip = false

	local line = zipline.Line
	local finish = zipline.End
	local start = zipline.Start
	local slider = script.Slider
	local animation = script.ZiplineHold

	start.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			if not isonzip then
				isonzip = true
				local character = hit.Parent
				local humanoid = hit.Parent.Humanoid
				local sliderclone = slider:Clone()
				sliderclone.Parent = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines
				sliderclone.PrimaryPart.Position = start.Position
				local sliderpart = sliderclone.SliderPart
				local movingsliderpart = sliderclone.Part
				local weld = Instance.new("Weld")
				weld.Part0 = character.Head
				weld.Part1 = sliderpart
				weld.Parent = sliderpart
				sliderpart.CFrame = character.Head.CFrame
				local tweeninfo = TweenInfo.new(2)
				local goal = {}
				goal.CFrame = finish.CFrame
				local tween = tweenservice:Create(movingsliderpart, tweeninfo, goal)
				tween:Play()
				local loadanimation = humanoid:LoadAnimation(animation)
				loadanimation:Play()
				while not controls:GetActiveController():GetIsJumping() do
					runservice.Heartbeat:Wait()
					print("Wait")
				end
				print("Jumped")
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				wait(2)
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				isonzip = false
			end
		end
	end)
end

Oh right, that’s because it’s stuck in an endless loop waiting for the player to jump. I didn’t account for the zipline ending. What we can do is wrap the while loop in a coroutine. What this does is it runs the loop on another thread, so both the while loop and the rest of the function can run at the same time.

coroutine.wrap(function()
	while not controls:GetActiveController():GetIsJumping() do
		runservice.Heartbeat:Wait()
	end
end)()

But now if the zipline stops before you jump, the coroutine will still continue to wait until you jump. We don’t want that. Instead, we need to tell it to stop if isonzip = false.

coroutine.wrap(function()
	while isonzip and not controls:GetActiveController():GetIsJumping() do
		runservice.Heartbeat:Wait()
	end
end)()
1 Like

Heyo AstroCode! I have ran into one last peculiar problem. Whenever a player jumps into the start, the player will just teleport to the same spot which is the lobby. I am not sure why this is happening. Is there something wrong with my script?

Script:

repeat wait() until game.Workspace:WaitForChild("Tower of Troubling Tutorials")
local ziplines = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines:GetChildren()

local tweenservice = game:GetService("TweenService")
local runservice = game:GetService("RunService")

local player = game.Players.LocalPlayer
local playermodule = require(player:WaitForChild("PlayerScripts"):WaitForChild("PlayerModule"))
local controls = playermodule:GetControls()

for i, zipline in pairs(ziplines) do
	local isonzip = false

	local line = zipline.Line
	local finish = zipline.End
	local start = zipline.Start
	local speed = zipline.Speed
	local slider = script.Slider
	local animation = script.ZiplineHold

	start.Touched:Connect(function(hit)
		if not isonzip and player.Character and hit:IsDescendantOf(player.Character) then
			isonzip = true
			local character = player.Character
			local humanoid = character.Humanoid
			local sliderclone = slider:Clone()
			sliderclone.Parent = game.Workspace:WaitForChild("Tower of Troubling Tutorials").Ziplines
			sliderclone.PrimaryPart.CFrame = start.CFrame
			local sliderpart = sliderclone.SliderPart
			local movingsliderpart = sliderclone.Part
			local weld = Instance.new("Weld")
			weld.Part0 = character.Head
			weld.Part1 = sliderpart
			weld.C1 = CFrame.new(0,-0.9,0)
			weld.Parent = sliderpart
			sliderpart.CFrame = character.Head.CFrame
			local tweeninfo = TweenInfo.new(speed.Value)
			local goal = {}
			goal.CFrame = finish.CFrame
			local tween = tweenservice:Create(movingsliderpart, tweeninfo, goal)
			tween:Play()
			local loadanimation = humanoid:LoadAnimation(animation)
			loadanimation:Play()
			coroutine.wrap(function()
				while isonzip and not controls:GetActiveController():GetIsJumping() do
					runservice.Heartbeat:Wait()
				end
				weld:Destroy()
				loadanimation:Stop()
				sliderclone:Destroy()
				isonzip = false
			end)()
			wait(speed.Value)
			weld:Destroy()
			loadanimation:Stop()
			sliderclone:Destroy()
			isonzip = false
		end
	end)
end

I’m not sure, there’s a lot going on in your code. A video might help.

1 Like