I’m attempting to implement an “Auto-Move” feature similar to the Elder Scrolls. The player presses a button and the player’s character moves in the direction the camera is pointed until the player either presses the button again or presses one of the direction keys.
According to the documentation:
voidMove ( Vector3 walkDirection , bool relativeToCamera )
Causes the player’s character to walk in the given direction until stopped, or interrupted by the player (by using their controls).
So in theory this should do exactly what I want but when I hit the C key the character just stands there. Here’s the code I’ve written, which is a combination of examples straight out of the documentation as well.
local function handleAction(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
game.Players.LocalPlayer:Move(Vector3.new(0, 0, -1), true)
end
end
ContextActionService:BindAction("Auto-Move", handleAction, true, Enum.KeyCode.C, Enum.KeyCode.ButtonR1)
Have you tried printing to see what the exact problem is? Your function not might be running, maybe try UserInputService instead of ContextActionService for registering button presses.
I cobbled together a script that should do what you want:
local ContextActionService = game:GetService("ContextActionService")
local LocalPlayer = game:GetService("Players").LocalPlayer
local cancel = false
local function handleAction(actionName, inputState, inputObject)
if not LocalPlayer.Character then return end
local Character = LocalPlayer.Character
local Humanoid = Character.Humanoid
if inputState == Enum.UserInputState.Begin then
cancel = not cancel
while cancel do
Humanoid:MoveTo(Character.PrimaryPart.CFrame.LookVector + Character.PrimaryPart.Position)
Humanoid.MoveToFinished:Wait()
end
end
end
ContextActionService:BindAction("Auto-Move", handleAction, true, Enum.KeyCode.C, Enum.KeyCode.ButtonR1)
The only thing that you might want to change is that it moves the character in the direction that it is facing rather than moving in the direction the camera is facing.
local ContextActionService = game:GetService("ContextActionService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local AUTO_MOVE_START_KEYS_LIST = { Enum.KeyCode.C, Enum.KeyCode.ButtonR1 }
local DIRECTION_MOVE_KEYS_LIST = { Enum.KeyCode.W, Enum.KeyCode.A, Enum.KeyCode.S, Enum.KeyCode.D }
local getLocalPlayerHumanoid = nil
do
local cachedLocalPlayerHumanoid: Humanoid? = nil
function getLocalPlayerHumanoid()
if cachedLocalPlayerHumanoid then
return cachedLocalPlayerHumanoid
end
local character = localPlayer.Character
if not character then
return
end
local humanoid: Humanoid? = character:FindFirstChildOfClass("Humanoid")
if not humanoid then
return
end
cachedLocalPlayerHumanoid = humanoid
humanoid.AncestryChanged:Connect(function()
if not humanoid:IsDescendantOf(game) then
cachedLocalPlayerHumanoid = nil
end
end)
return humanoid
end
end
local ancestryChangedConnection: RBXScriptConnection? = nil
local diedConnection: RBXScriptConnection? = nil
local autoMoveThread: thread? = nil
local function closeAutoMoveThread()
ancestryChangedConnection:Disconnect()
diedConnection:Disconnect()
coroutine.close(autoMoveThread)
autoMoveThread = nil
end
local function handleAction(_, inputState: Enum.UserInputState, inputObject: InputObject)
if inputState == Enum.UserInputState.Begin then
if autoMoveThread then
closeAutoMoveThread()
local humanoid = getLocalPlayerHumanoid()
if humanoid then
local rootPart = humanoid.RootPart
if rootPart then
humanoid:MoveTo(rootPart.Position)
end
end
elseif table.find(AUTO_MOVE_START_KEYS_LIST, inputObject.KeyCode) then
for _, keyCode in ipairs(DIRECTION_MOVE_KEYS_LIST) do
if UserInputService:IsKeyDown(keyCode) then
return
end
end
local humanoid = getLocalPlayerHumanoid()
if humanoid then
local rootPart = humanoid.RootPart
if rootPart then
autoMoveThread = coroutine.create(function()
while true do
local camera = workspace.CurrentCamera
if camera then
humanoid:MoveTo(camera.CFrame.LookVector * 10 + rootPart.Position)
end
task.wait()
end
end)
coroutine.resume(autoMoveThread)
ancestryChangedConnection = humanoid.AncestryChanged:Connect(function()
if not humanoid:IsDescendantOf(game) then
closeAutoMoveThread()
end
end)
diedConnection = humanoid.Died:Connect(closeAutoMoveThread)
end
end
end
end
end
ContextActionService:BindActionAtPriority(
"Auto-Move",
handleAction,
true,
Enum.ContextActionPriority.Low.Value,
unpack(AUTO_MOVE_START_KEYS_LIST),
unpack(DIRECTION_MOVE_KEYS_LIST)
)
local AutoMove = false
local function handleAction(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
AutoMove = not AutoMove
end
end
local player = game.Players.LocalPlayer
local function onRenderStep(deltaTime)
if AutoMove then
player:Move(Vector3.new(0, 0, -1), true)
end
end
local ContextActionService = game:GetService("ContextActionService")
ContextActionService:BindAction("Auto-Move", handleAction, true, Enum.KeyCode.C, Enum.KeyCode.ButtonR1)
local RunService = game:GetService("RunService")
RunService.RenderStepped:Connect(onRenderStep)
This is a lot simpler and cleaner. The only difference is that it only stops if you hit the Auto-Move key again.