如何在2.5D Obby中实现手柄D-Pad移动以解决摇杆漂移问题
2.5D Obby实现游戏手柄D-Pad持续移动方案
我正在制作一款2.5D Obby,由于很多使用摇杆的玩家存在摇杆漂移问题,想实现D-Pad(方向键)移动功能,避免玩家因漂移失控,但不知道正确的脚本写法。我把以下本地脚本放在了StarterPlayerScripts中:
local UserInputService = game:GetService("UserInputService") local player = game.Players.LocalPlayer local function onInput(input, gameProcessed) if gameProcessed then return end if input.UserInputType == Enum.UserInputType.Gamepad1 then if input.KeyCode == Enum.KeyCode.DPadUp then print("DPAD Up Pressed") player.Character:Move(Vector3.new(0, 0, -1)) elseif input.KeyCode == Enum.KeyCode.DPadDown then print("DPAD Down Pressed") player.Character:Move(Vector3.new(0, 0, 1)) elseif input.KeyCode == Enum.KeyCode.DPadLeft then print("DPAD Left Pressed") player.Character:Move(Vector3.new(-1, 0, 0)) elseif input.KeyCode == Enum.KeyCode.DPadRight then print("DPAD Right Pressed") player.Character:Move(Vector3.new(1, 0, 0)) end end end UserInputService.InputBegan:Connect(onInput)
原脚本的问题
原脚本仅在InputBegan触发时调用一次Move方法,只能让角色移动一小段距离,无法实现按住D-Pad时的持续移动;同时未处理角色未加载的情况,也没有匹配2.5D视角的方向逻辑,移动方向会和相机视角脱节。
修正后的脚本
local UserInputService = game:GetService("UserInputService") local RunService = game:GetService("RunService") local Players = game:GetService("Players") local player = Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local humanoid = character:WaitForChild("Humanoid") -- 记录D-Pad按键状态 local dpadState = { Up = false, Down = false, Left = false, Right = false } -- 更新按键状态的通用函数 local function updateDpadState(input, isPressed) if input.UserInputType ~= Enum.UserInputType.Gamepad1 then return end if input.KeyCode == Enum.KeyCode.DPadUp then dpadState.Up = isPressed elseif input.KeyCode == Enum.KeyCode.DPadDown then dpadState.Down = isPressed elseif input.KeyCode == Enum.KeyCode.DPadLeft then dpadState.Left = isPressed elseif input.KeyCode == Enum.KeyCode.DPadRight then dpadState.Right = isPressed end end -- 监听按键按下 UserInputService.InputBegan:Connect(function(input, gameProcessed) if gameProcessed then return end updateDpadState(input, true) end) -- 监听按键松开 UserInputService.InputEnded:Connect(function(input, gameProcessed) if gameProcessed then return end updateDpadState(input, false) end) -- 处理角色重新加载 player.CharacterAdded:Connect(function(newChar) character = newChar humanoid = character:WaitForChild("Humanoid") end) -- 每帧更新移动 RunService.Heartbeat:Connect(function() if not character or not humanoid or humanoid.Health <= 0 then return end -- 计算基础移动方向 local moveDir = Vector3.new(0, 0, 0) if dpadState.Up then moveDir += Vector3.new(0, 0, -1) end if dpadState.Down then moveDir += Vector3.new(0, 0, 1) end if dpadState.Left then moveDir += Vector3.new(-1, 0, 0) end if dpadState.Right then moveDir += Vector3.new(1, 0, 0) end -- 归一化方向,避免斜向移动速度过快 if moveDir.Magnitude > 0 then moveDir = moveDir.Unit end -- 匹配相机视角,让移动符合2.5D视角 local camera = workspace.CurrentCamera local cameraForward = camera.CFrame.LookVector cameraForward = Vector3.new(cameraForward.X, 0, cameraForward.Z).Unit local cameraRight = camera.CFrame.RightVector cameraRight = Vector3.new(cameraRight.X, 0, cameraRight.Z).Unit local finalMoveDir = (cameraForward * moveDir.Z) + (cameraRight * moveDir.X) humanoid:Move(finalMoveDir, false) end)
关键改进说明
- 持续移动逻辑:通过
InputBegan和InputEnded记录按键状态,在Heartbeat每帧循环中处理移动,实现按住D-Pad时的持续移动 - 角色加载处理:监听
CharacterAdded事件,处理角色死亡重生或重新加载的情况 - 视角匹配:将基础移动方向转换为相机视角下的方向,确保2.5D游戏中移动方向符合玩家视觉预期
- 速度归一化:斜向移动时归一化方向向量,避免同时按两个方向时移动速度过快
内容的提问来源于stack exchange,提问作者Exauce John B.
相关产品推荐
相关产品推荐

