Hello! I’m currently trying to create a custom movement system similar to this game on Roblox Studio!
I suspect they used vector force to create their movement system, so I did just that.
After disabling the default controls, animations, and making the character into physics mode. I applied anti-gravity and aligned orientation, to reduce friction and keep the player standing.
I successfully made it so that when the player pressed the WASD keys the player can move around.
A vector force called “MovementForce” is added to the HumanoidRootPart and goes in the direction corresponding to which the key is pressed
I also made it so that when the player goes too fast, another Vector force object tries to cancel the momentum by applying a force in the opposite direction. A Vector force called “CancelForce” is added to the HumanoidRootPart, and a function is binded to the renderstep, that checks and sets the force.
The problem I am having is that when the player moves forward, then left, an arc/curve is formed. Which slowly moves the player in the requested direction. As shown here:
However in Ragdoll Universe’s Movement System the turn is more immediate with minimal arc/curve:
How would I go about achieving this goal?
I have tried adding a “HelperForce” which applies a force in the direction you pressed your key in, enabling and disabling after a short period of time, to help set the character on the right track. Sadly this does not work.
Currently, I am experimenting with applying a cancel force every time the player releases a key.
Any ideas? :DD
Code:
local BaseMovement = {}
BaseMovement.__index = BaseMovement
--- Services
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local LocalPlayer = Players.LocalPlayer
--- Modules
local KeyBinds = require(script.Parent.Parent.Keybinds)
--- Local Func
function BaseMovement.New(value)
local self = setmetatable({}, BaseMovement)
self.SPEED = 2000
self.CANCEL_SEVERITY = 1
self.GRAVITY_LEVEL = 0.5
self.MOMENTUM_CAP = 40
self.JUMP_HEIGHT = 20000
self.onGround = false
self.justLanded = false
self.isMoving = false
-- may not need these
self.GravityForce = false
self.MovementForce = false
return self
end
function BaseMovement:Enable()
self:Disable()
self:SetForces() -- puts all neccesarry forces into the character
self:SetAlignment() -- puts all neccesarry alignment into character
local inputFunctions = {
[KeyBinds.keyboardWalkForward] = function(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
--print("Pressed 'W'")
self.MovementForce.Force += Vector3.new(0,0,-self.SPEED)
else
--print("Released 'W'")
self.MovementForce.Force += Vector3.new(0,0,self.SPEED)
end
--print(self.MovementForce.Force)
end,
[KeyBinds.keyboardWalkLeft] = function(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
self.MovementForce.Force += Vector3.new(-self.SPEED,0,0)
--print("Pressed 'A'")
else
self.MovementForce.Force += Vector3.new(self.SPEED,0,0)
--print("Released 'A'")
end
end,
[KeyBinds.keyboardWalkBackward] = function(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
self.MovementForce.Force += Vector3.new(0,0,self.SPEED)
else
self.MovementForce.Force += Vector3.new(0,0,-self.SPEED)
end
end,
[KeyBinds.keyboardWalkRight] = function(actionName, inputState, inputObject)
if inputState == Enum.UserInputState.Begin then
self.MovementForce.Force += Vector3.new(self.SPEED,0,0)
else
self.MovementForce.Force += Vector3.new(-self.SPEED,0,0)
end
end,
[KeyBinds.keyboardJump] = function(actionName, inputState, inputObject)
print("Space was pressed")
end,
}
local inputs = {}
for input, func in pairs(inputFunctions) do
table.insert(inputs, input)
end
ContextActionService:BindAction("Movement", function(actionName, inputState, inputObject) -- this method may not be useful for movie buttons when setting positions, useful only when it is "False"
if inputFunctions[inputObject.KeyCode] then
inputFunctions[inputObject.KeyCode](actionName, inputState, inputObject)
elseif inputFunctions[inputObject.UserInputType] then
inputFunctions[inputObject.UserInputType](actionName, inputState, inputObject)
end
end, false, table.unpack(inputs))
RunService:BindToRenderStep("temp", Enum.RenderPriority.Camera.Value, function()
--
--[[]]
local velocity, magnitude = self:GetPlayerAxisMagnitude(true,false,true)
local desiredDirection = self:GetPlayerMovementVector3(true,false,true).Unit
if self.MovementForce.Force == Vector3.new(0,0,0) then
desiredDirection = Vector3.new(0,0,0)
end
if magnitude > self.MOMENTUM_CAP then -- need to compare and check directions using vector.unit
--apply cancel
self.CancelForce.Force = self:GetPlayerMovementVector3(true,false,true) * -1 * self.CANCEL_SEVERITY
self.CancelForce.Enabled = true
else
-- disable cancel
self.CancelForce.Force = Vector3.new(0,0,0)
self.CancelForce.Enabled = false
end
end)
end
function BaseMovement:Disable()
--print("Disabled")
ContextActionService:UnbindAction("Movement")
RunService:UnbindFromRenderStep("temp")
end
function BaseMovement:GetMass(Model)
local mass = 0
for i, v in pairs(Model:GetChildren()) do
if v:IsA("BasePart") then
mass+= v:GetMass()
end
end
return mass
end
function BaseMovement:GetPlayerAxisMagnitude (x,y,z)
local velocity= LocalPlayer.Character.HumanoidRootPart.Velocity
if x == false then
velocity -= Vector3.new(velocity.X,0,0)
end
if y == false then
velocity -= Vector3.new(0,velocity.Y,0)
end
if z == false then
velocity -= Vector3.new(0,0,velocity.Z)
end
return velocity, velocity.Magnitude
end
function BaseMovement:GetPlayerMovementVector3(x,y,z)
local vector = self.MovementForce.Force
if x == false then
vector -= Vector3.new(vector.X,0,0)
end
if y == false then
vector -= Vector3.new(0,vector.Y,0)
end
if z == false then
vector -=Vector3.new(0,0,vector.Z)
end
return vector
end
function BaseMovement:PrintTable()
print("BASE_MOVEMENT:")
print(self)
print(getmetatable(self))
self:PrintTable2()
end
return BaseMovement