O Humanoid nativo do Roblox é insuficiente para jogos de ação rápida, apresentando travamentos em degraus e instabilidades em plataformas móveis.
Criar um controlador físico personalizado garante controle milimétrico e previsível. Usando uma cápsula suspensa por molas virtuais com VectorForce e projetando a velocidade sobre as normais do terreno via raycast, obtém-se movimentação suave e responsiva.
1. Gargalos do Humanoid Padrão em Jogos de Ação
Por que projetos competitivos optam por controladores independentes:
- Máquina de estados rígida: Transições lentas impedem mudanças rápidas de curso.
- Projeção em plataformas: Descompassos físicos que arremessam o jogador para longe.
- Trancos em degraus: Saltos bruscos de posição que causam tremulação na câmera.
- Controle determinístico: Cálculo exato da velocidade a cada quadro no Heartbeat.
2. Cápsula Flutuante e Suspensão com VectorForce
Movimento sem atrito direto para deslizar suavemente por obstáculos:
- Suspensão virtual: Raycast para baixo aplicando força elástica para sustentar o peso.
- Casco sem atrito: Cápsula lisa que nunca se prende em quinas ou frestas.
- Equilíbrio AlignOrientation: Mantém o personagem em pé sem tombamentos.
- Resposta LinearVelocity: Resposta de velocidade instantânea sem aceleração lenta.
--!strict
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")
local Players = game:GetService("Players")
local CustomController = {}
local player = Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local hrp = char:WaitForChild("HumanoidRootPart") :: BasePart
local TARGET_HEIGHT = 4.2
local SPRING_STIFFNESS = 1800
local SPRING_DAMPING = 160
local WALK_SPEED = 24
local RAY_PARAMS = RaycastParams.new()
RAY_PARAMS.FilterType = RaycastFilterType.Exclude
local linearVelocity = Instance.new("LinearVelocity")
linearVelocity.MaxForce = 40000
linearVelocity.VelocityConstraintMode = Enum.VelocityConstraintMode.Vector
linearVelocity.RelativeTo = Enum.ActuatorRelativeTo.World
local attachment = Instance.new("Attachment")
attachment.Parent = hrp
linearVelocity.Attachment0 = attachment
linearVelocity.Parent = hrp
function CustomController.Update(dt: number)
local moveDir = Vector3.zero
local cam = Workspace.CurrentCamera
if UserInputService:IsKeyDown(Enum.KeyCode.W) then moveDir += cam.CFrame.LookVector end
if UserInputService:IsKeyDown(Enum.KeyCode.S) then moveDir -= cam.CFrame.LookVector end
if UserInputService:IsKeyDown(Enum.KeyCode.D) then moveDir += cam.CFrame.RightVector end
if UserInputService:IsKeyDown(Enum.KeyCode.A) then moveDir -= cam.CFrame.RightVector end
moveDir = Vector3.new(moveDir.X, 0, moveDir.Z)
if moveDir.Magnitude > 0.01 then moveDir = moveDir.Unit end
RAY_PARAMS.FilterDescendantsInstances = { char }
local ray = Workspace:Raycast(hrp.Position, Vector3.new(0, -TARGET_HEIGHT * 1.5, 0), RAY_PARAMS)
local vForce = 0
local targetVel = moveDir * WALK_SPEED
if ray and ray.Instance and ray.Instance.CanCollide then
local dist = (hrp.Position - ray.Position).Magnitude
targetVel = moveDir - (ray.Normal * moveDir:Dot(ray.Normal))
targetVel = targetVel.Unit * WALK_SPEED
local err = TARGET_HEIGHT - dist
vForce = (err * SPRING_STIFFNESS) - (hrp.AssemblyLinearVelocity.Y * SPRING_DAMPING)
end
linearVelocity.VectorVelocity = Vector3.new(targetVel.X, targetVel.Y + (vForce * dt), targetVel.Z)
end
RunService.Heartbeat:Connect(CustomController.Update)
return CustomController
3. Raycast no Solo e Projeção Vetorial em Rampas
Mantendo velocidade constante em subidas e descidas íngremes:
- Vetor normal do chão: Identificação precisa da inclinação através do raycast.
- Projeção matemática: Alinhamento do vetor de avanço com o plano da rampa.
- Limite de inclinação: Escorregamento forçado em aclives acima de 45 graus.
- Previsão de quedas: Sondas auxiliares para detectar bordas de precipícios.
4. Inércia, Impulso e Mecânicas de Deslizamento
Adicionando movimentação dinâmica para jogos de corrida e parkour:
- Deslize ao agachar: Redução temporária de atrito durante corridas rápidas.
- Aceleração gravitacional: Ganho de velocidade ao deslizar ladeira abaixo.
- Retenção de embalo: Transição gradual de volta à caminhada normal.
- Manobras aéreas: Ajuste de curso no ar sem gerar aceleração ilimitada.
5. Sincronização de Animação e Pés com IKControl
Harmonia entre física do movimento e esqueleto 3D:
- Fim do deslizamento de passos: Ajuste do ritmo da animação conforme a velocidade real.
- Transição em 8 direções: Combinação harmoniosa de poses de movimento.
- Apoio firme com IKControl: Pés que tocam perfeitamente em degraus e pedras.
- Execução no cliente: Processamento físico no próprio dispositivo para evitar atrasos.
Frequently Asked Questions
Por que usar suspensão por mola em vez de tocar o solo?
O contato físico direto prende o personagem em quinas imperfeitas; a suspensão flutuante garante passagem contínua.
Como a projeção de vetores impede a perda de velocidade em rampas?
Ela redireciona o empuxo paralelamente à rampa em vez de bater contra ela.
Evita problemas de arremesso em plataformas móveis?
Sim, pois o controlador pode herdar diretamente a velocidade da plataforma detectada.