Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How do I add double jump to this fly script?

Currently, it's kind of hard to use because it only requires you to use one jump to active flying. How can I make it so you must double-tap jump to fly? I figure I'm going to need some sort of debounce, but I don't know where to put it.

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")

local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera;

local character = game.Players.LocalPlayer.CharacterAdded:Wait();
local hrp = character:WaitForChild("HumanoidRootPart");
local humanoid = character:WaitForChild("Humanoid");
local animate = character:WaitForChild("Animate");

while (not character.Parent) do character.AncestryChanged:Wait(); end
local idleAnim = humanoid:LoadAnimation(script:WaitForChild("IdleAnim"));
local moveAnim = humanoid:LoadAnimation(script:WaitForChild("MoveAnim"));
local lastAnim = idleAnim;

local bodyGyro = Instance.new("BodyGyro");
bodyGyro.maxTorque = Vector3.new(1, 1, 1)*10^6;
bodyGyro.P = 10^6;

local bodyVel = Instance.new("BodyVelocity");
bodyVel.maxForce = Vector3.new(1, 1, 1)*10^6;
bodyVel.P = 10^4;

local isFlying = false;
local isJumping = false;
local movement = {forward = 0, backward = 0, right = 0, left = 0};

-- functions

local function setFlying(flying)
	isFlying = flying;
	bodyGyro.Parent = isFlying and hrp or nil;
	bodyVel.Parent = isFlying and hrp or nil;
	bodyGyro.CFrame = hrp.CFrame;
	bodyVel.Velocity = Vector3.new();
	
	animate.Disabled = isFlying;
	
	if (isFlying) then
		lastAnim = idleAnim;
		lastAnim:Play();
	else
		lastAnim:Stop();
	end
end

local function onUpdate(dt)
	if (isFlying) then
		local cf = camera.CFrame;
		local direction = cf.rightVector*(movement.right - movement.left) + cf.lookVector*(movement.forward - movement.backward);
		
		if (direction:Dot(direction) > 0) then
			direction = direction.unit;
		end

		bodyGyro.CFrame = cf;
		bodyVel.Velocity = direction * humanoid.WalkSpeed * 3;
	end
end

local function onJumpRequest()
	if (not humanoid or humanoid:GetState() == Enum.HumanoidStateType.Dead) then
		return;
	end
	
	if (isFlying) then
		setFlying(false);
		isJumping = false;
	elseif (isJumping) then
		setFlying(true);
	end
end
	
local function onStateChange(old, new)
	if (new == Enum.HumanoidStateType.Landed) then	
		isJumping = false;
	elseif (new == Enum.HumanoidStateType.Jumping) then
		isJumping = true;
	end
end

local function movementBind(actionName, inputState, inputObject)
	if (inputState == Enum.UserInputState.Begin) then
		movement[actionName] = 1;
	elseif (inputState == Enum.UserInputState.End) then
		movement[actionName] = 0;
	end
	
	if (isFlying) then
		local isMoving = movement.right + movement.left + movement.forward + movement.backward > 0;
		local nextAnim = isMoving and moveAnim or idleAnim;
		if (nextAnim ~= lastAnim) then
			lastAnim:Stop();
			lastAnim = nextAnim;
			lastAnim:Play();
		end
	end
	
	return Enum.ContextActionResult.Pass;
end

-- connections

humanoid.StateChanged:Connect(onStateChange);
game:GetService("UserInputService").JumpRequest:Connect(onJumpRequest);

game:GetService("ContextActionService"):BindAction("forward", movementBind, false, Enum.PlayerActions.CharacterForward);
game:GetService("ContextActionService"):BindAction("backward", movementBind, false, Enum.PlayerActions.CharacterBackward);
game:GetService("ContextActionService"):BindAction("left", movementBind, false, Enum.PlayerActions.CharacterLeft);
game:GetService("ContextActionService"):BindAction("right", movementBind, false, Enum.PlayerActions.CharacterRight);

game:GetService("RunService").RenderStepped:Connect(onUpdate)

Thank you!

1 answer

I made it a timed solution, so you have to hit the spacebar twice kind of fast, to get the fly to work.. .13 seconds in between.. you can adjust this to 1 second or so if you like by changing it to 1, or 1.5.. The tracked time is stored in the variable lastjump_request

local uis = game:GetService("UserInputService")
local rs = game:GetService("RunService")

local player = game.Players.LocalPlayer
local camera = game.Workspace.CurrentCamera;

local character = game.Players.LocalPlayer.CharacterAdded:Wait();
local hrp = character:WaitForChild("HumanoidRootPart");
local humanoid = character:WaitForChild("Humanoid");
local animate = character:WaitForChild("Animate");
local lastjump_request = game.Workspace.DistributedGameTime
while (not character.Parent) do character.AncestryChanged:Wait(); end
local idleAnim = humanoid:LoadAnimation(script:WaitForChild("IdleAnim"));
local moveAnim = humanoid:LoadAnimation(script:WaitForChild("MoveAnim"));
local lastAnim = idleAnim;

local bodyGyro = Instance.new("BodyGyro");
bodyGyro.maxTorque = Vector3.new(1, 1, 1)*10^6;
bodyGyro.P = 10^6;

local bodyVel = Instance.new("BodyVelocity");
bodyVel.maxForce = Vector3.new(1, 1, 1)*10^6;
bodyVel.P = 10^4;

local isFlying = false;
local isJumping = false;
local movement = {forward = 0, backward = 0, right = 0, left = 0};

-- functions

local function setFlying(flying)
    isFlying = flying;
    bodyGyro.Parent = isFlying and hrp or nil;
    bodyVel.Parent = isFlying and hrp or nil;
    bodyGyro.CFrame = hrp.CFrame;
    bodyVel.Velocity = Vector3.new();

    animate.Disabled = isFlying;

    if (isFlying) then
        lastAnim = idleAnim;
        lastAnim:Play();
    else
        lastAnim:Stop();
    end
end

local function onUpdate(dt)
    if (isFlying) then
        local cf = camera.CFrame;
        local direction = cf.rightVector*(movement.right - movement.left) + cf.lookVector*(movement.forward - movement.backward);

        if (direction:Dot(direction) > 0) then
            direction = direction.unit;
        end

        bodyGyro.CFrame = cf;
        bodyVel.Velocity = direction * humanoid.WalkSpeed * 3;
    end
end

local function onJumpRequest()
    if (not humanoid or humanoid:GetState() == Enum.HumanoidStateType.Dead) then
        return;
    end
	--print("JUMP REQESTED")
    if (isFlying) then
        setFlying(false);
        isJumping = false;
    elseif (isJumping) then
		if game.Workspace.DistributedGameTime - lastjump_request > .13 then
			setFlying(true);
				
		end
        lastjump_request = game.Workspace.DistributedGameTime
    end
end

local function onStateChange(old, new)
    if (new == Enum.HumanoidStateType.Landed) then  
        isJumping = false;
    elseif (new == Enum.HumanoidStateType.Jumping) then
        isJumping = true;
    end
end

local function movementBind(actionName, inputState, inputObject)
    if (inputState == Enum.UserInputState.Begin) then
        movement[actionName] = 1;
    elseif (inputState == Enum.UserInputState.End) then
        movement[actionName] = 0;
    end

    if (isFlying) then
        local isMoving = movement.right + movement.left + movement.forward + movement.backward > 0;
        local nextAnim = isMoving and moveAnim or idleAnim;
        if (nextAnim ~= lastAnim) then
            lastAnim:Stop();
            lastAnim = nextAnim;
            lastAnim:Play();
        end
    end

    return Enum.ContextActionResult.Pass;
end

-- connections

humanoid.StateChanged:Connect(onStateChange);
game:GetService("UserInputService").JumpRequest:Connect(onJumpRequest);

game:GetService("ContextActionService"):BindAction("forward", movementBind, false, Enum.PlayerActions.CharacterForward);
game:GetService("ContextActionService"):BindAction("backward", movementBind, false, Enum.PlayerActions.CharacterBackward);
game:GetService("ContextActionService"):BindAction("left", movementBind, false, Enum.PlayerActions.CharacterLeft);
game:GetService("ContextActionService"):BindAction("right", movementBind, false, Enum.PlayerActions.CharacterRight);

game:GetService("RunService").RenderStepped:Connect(onUpdate)

This discussion is preserved as it was. New answers, comments, and votes are closed.