I’m gonna keep this simple. I’m currently creating a game which is a very long and challenging obby. I want to give the players their own freedom to set their checkpoints wherever they want too. The players would press the button C on their keyboard to set the checkpoint and then the letter V to teleport back to that checkpoint they have set. The problem is, I am very new to scripting, and I have absolutely no idea how to make that work.
If anyone has any suggestions, it would be much appreciated!
Thank you.
Create a function using ContextActionService (BindAction) that listens to the C and V keycodes
If the key is C then it sets the checkpoint, by getting their Character’s HumanoidRootPartPosition and setting it as a variable.
If the key is V then they’re teleported via MoveTo back to that saved position.
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
local SET_CHECKPOINT_KEY = Enum.KeyCode.C
local GOTO_CHECKPOINT_KEY = Enum.KeyCode.V
local SavedCheckpoint;
local function doesPlayerHaveCharacter()
return (LocalPlayer.Character and LocalPlayer.Character:IsDescendantOf(workspace) and LocalPlayer.Character:FindFirstChild("HumanoidRootPart"))
end
local function checkpointAction(action, ioState, ioObject)
if ioState == Enum.UserInputState.Begin and doesPlayerHaveCharacter() then
if ioObject.KeyCode == SET_CHECKPOINT_KEY then
SavedCheckpoint = LocalPlayer.Character.HumanoidRootPart.Position
print("Saved Checkpoint!") -- You might want to add some kind of pop-up?
elseif SavedCheckpoint then
LocalPlayer.Character:MoveTo(SavedCheckpoint)
end
end
end
ContextActionService:BindAction("SetCheckpointAction", checkpointAction, true, SET_CHECKPOINT_KEY, GOTO_CHECKPOINT_KEY)
I’m not usually one for giving free scripts, but since this is a rather easy one, I’m going to help you out while hopefully making you learn something.
So, first thing first, you would want to make a localscript somewhere in the Player. This would work best in StarterPlayerScripts.
Inside the script, it would look something like this:
local Players = game:GetService('Players') -- This gets the "Players" service
local Player = Players.LocalPlayer -- This gets the local Player
local UserInputService = game:GetService('UserInputService') -- This is the service we use to detect buttons clicked
local LastSavedPosition = nil -- The last position the player saved, starts as nil
UserInputService.InputBegan:Connect(function(Input, GameProcessed) -- Setting up a listening event for when a button is clicked, Input is the button clicked and GameProcessed is whether it was inside a Gui Object
if not GameProcessed then -- We don't want this to run if the button was pressed inside a Gui like the roblox chat, do we?
if Input.KeyCode == Enum.KeyCode.C then -- Did the player press C?
print('C was pressed! Let\'s make sure the player\'s character and head exists before saving the position...')
if Player.Character and Player.Character:FindFirstChild('Head') then
local Head = Player.Character.Head -- Making the player's head a variable to make this easier
LastSavedPosition = Head.Position
print('Saved!')
end
elseif Input.KeyCode == Enum.KeyCode.V then -- No need to add a whole new listening event for this, just use elseif!
print('V was pressed! Player wants to teleport to last saved position')
if LastSavedPosition then -- We need to make sure the player actually has a saved position to teleport to
print('We got a saved position! Let\'s get the character and then teleport')
if Player.Character then
Player.Character:MoveTo(LastSavedPosition)
print('tada')
end
else
print('Woah! Save a position first!')
end
end
end
end)
This particular script might have unintended consequences. Since the Head is not the root part of the Humanoid, the teleport position will be moved up - this could facilitate fly glitching. Otherwise, we seem to have been working on the same thing!
That might be true! However, I didn’t know if he was using R6 or R15, so I figured getting the Head was the safest bet. I didn’t think to get the HumanoidRootPart.
Hey thank you for the input! I used your script to test it out, and for the most part it works perfectly. However, as unix_system stated, there is an issue with setting the checkpoint next to a wall, as when you teleport back to that spot, it does teleport you onto the top of the wall instead of the position it was set. I changed it from Head to HumanoidRootPart, yet the problem still insists. Do you suspect there is a fix for that? If not I will tackle that problem in another way, such as the layout of the map
There is a fix for that, yeah. Instead of using MoveTo(), we can try CFrame.
local Players = game:GetService('Players') -- This gets the "Players" service
local Player = Players.LocalPlayer -- This gets the local Player
local UserInputService = game:GetService('UserInputService') -- This is the service we use to detect buttons clicked
local LastSavedPosition = nil -- The last position the player saved, starts as nil
function GetHumanoidRootPart()
return Player.Character and Player.Character:FindFirstChild('HumanoidRootPart') or nil -- Returns HumanoidRootPart if found or nil
end
UserInputService.InputBegan:Connect(function(Input, GameProcessed) -- Setting up a listening event for when a button is clicked, Input is the button clicked and GameProcessed is whether it was inside a Gui Object
if not GameProcessed then -- We don't want this to run if the button was pressed inside a Gui like the roblox chat, do we?
if Input.KeyCode == Enum.KeyCode.C then -- Did the player press C?
print('C was pressed! Let\'s make sure the player\'s character and HumanoidRootPart exists before saving the position...')
local HRP = GetHumanoidRootPart() -- Getting the HumanoidRootPart
if HRP then -- Does the HumanoidRootPart exist?
LastSavedPosition = HRP.CFrame
print('Saved!')
end
elseif Input.KeyCode == Enum.KeyCode.V then -- No need to add a whole new listening event for this, just use elseif!
print('V was pressed! Player wants to teleport to last saved position')
if LastSavedPosition then -- We need to make sure the player actually has a saved position to teleport to
print('We got a saved position! Let\'s get the character and then teleport')
local HRP = GetHumanoidRootPart() -- Getting the HumanoidRootPart
if HRP then -- Does the HumanoidRootPart exist?
HRP.CFrame = LastSavedPosition
print('tada')
end
else
print('Woah! Save a position first!')
end
end
end
end)
local Players = game:GetService('Players') -- This gets the "Players" service
local Player = Players.LocalPlayer -- This gets the local Player
local UserInputService = game:GetService('UserInputService') -- This is the service we use to detect buttons clicked
local LastSavedPosition = nil -- The last position the player saved, starts as nil
function GetHumanoidRootPart()
return Player.Character and Player.Character:FindFirstChild('HumanoidRootPart') or nil -- Returns HumanoidRootPart if found or nil
end
UserInputService.InputBegan:Connect(function(Input, GameProcessed) -- Setting up a listening event for when a button is clicked, Input is the button clicked and GameProcessed is whether it was inside a Gui Object
if not GameProcessed then -- We don't want this to run if the button was pressed inside a Gui like the roblox chat, do we?
if Input.KeyCode == Enum.KeyCode.C or Input.KeyCode == Enum.KeyCode.V then -- One of the buttons we were listening to was pressed!
local HRP = GetHumanoidRootPart() -- Since both buttons require the HumanoidRootPart, we\'ll start with that
if HRP then
print('HumanoidRootPart exists!')
if Input.KeyCode == Enum.KeyCode.C then -- Was C pressed?
print('C was pressed!')
LastSavedPosition = HRP.CFrame
print('Saved!')
else -- No? Must be V then
print('V was pressed!')
if LastSavedPosition then -- We need to make sure the player actually has a saved position to teleport to
HRP.CFrame = LastSavedPosition
print('tada')
else
print('Woah! Save a position first!')
end
end
end
end
end
end)