I’m writing a movement system and how it works right now is that it checks every frame if a certain value is true and if it is true and it acts accordingly. This is the code:
P.S. I tried to add comments to whatever I think may be vague but most of it is pretty self explanatory to me
local MovementController = {}
local StateControllerModule = require(script.Parent.StateController)
local AnimationControllerModule = require(script.Parent.AnimationController)
local UIS = game:GetService("UserInputService")
MovementController.__index = MovementController
function MovementController.new(player : Player)
local self = setmetatable({}, MovementController)
self.Character = player.Character or player.CharacterAdded:Wait()
self.Humanoid = self.Character:WaitForChild("Humanoid")
self.Player = player
self.Animations = AnimationControllerModule.new(self.Humanoid.Animator)
self.StateController = StateControllerModule.new(player)
self.sprintToggled = false
self.shiftLocked = false
self.facingCamera = false
self.lastDirection = nil
self.currentDirection = "Idle"
self.lastState = nil
self.WalkSpeed = 16
self.SprintSpeed = 30
self.isJumping = true --none of this does anything atm
self.canJump = false
self.jumpDelay = 1
self.movementKeys = {
[Enum.KeyCode.LeftAlt] = function() self.sprintToggled = not self.sprintToggled end,
[Enum.KeyCode.LeftShift] = function() self:ToggleShiftLock() end,
[Enum.KeyCode.Q] = function() print("call dash function") end,
[Enum.KeyCode.Space] = function() print("jump") end
}
return self
end
function MovementController:Init()--self explanatory
UIS.InputBegan:Connect(function(input, gpe)
if gpe then return end
if self.movementKeys[input.KeyCode] then
self.movementKeys[input.KeyCode]()
end
end)
game:GetService("RunService").RenderStepped:Connect(function()
self:Update()
end)
end
function MovementController:Update()
local moving = self.Humanoid.MoveDirection.Magnitude > 0.1
local camera = workspace.CurrentCamera
local HRP = self.Character:WaitForChild("HumanoidRootPart")
local rootPart = self.Character:WaitForChild("HumanoidRootPart")
local moveDirection = self.Humanoid.MoveDirection
local dot = rootPart.CFrame.LookVector:Dot(moveDirection)
local sideDot = rootPart.CFrame.RightVector:Dot(moveDirection)
local currentState = self.StateController:GetState()
if self.shiftLocked and self.sprintToggled then --self explanatory
self.facingCamera = false
elseif self.shiftLocked and not self.sprintToggled then
self.facingCamera = true
elseif not self.shiftLocked and self.sprintToggled then
self.facingCamera = false
else
self.facingCamera = false
end
if moving then --player is moving
if self.sprintToggled then
self.lastState = currentState
self.StateController:SetState("Sprinting")
self.Humanoid.WalkSpeed = self.SprintSpeed
else
self.lastState = currentState
self.StateController:SetState("Walking")
self.Humanoid.WalkSpeed = self.WalkSpeed
end
if self.shiftLocked and currentState == "Walking" then --changes direction based on player movement if they are in shift lock
if dot > 0.5 then
self.lastDirection = self.currentDirection
self.currentDirection = "Forward"
elseif dot < -0.5 then
self.lastDirection = self.currentDirection
self.currentDirection = "Backward"
end
if sideDot > 0.5 then
self.lastDirection = self.currentDirection
self.currentDirection = "Right"
elseif sideDot < -0.5 then
self.lastDirection = self.currentDirection
self.currentDirection = "Left"
end
else
self.lastDirection = self.currentDirection
self.currentDirection = "Forward"
end
else --not moving
self.lastState = currentState
self.lastDirection = self.currentDirection
self.StateController:SetState("Idle")
self.currentDirection = "Idle"
end
if self.facingCamera then --this is so that the player looks at the camera when they are in shift lock but if they start sprinting then they stop facing the camera and turn to wherever they wan
HRP.CFrame = CFrame.lookAt(HRP.Position, HRP.Position + Vector3.new(camera.CFrame.LookVector.X, 0, camera.CFrame.LookVector.Z))
end
--print("state: " .. self.StateController:GetState() .. ", direction: " .. self.lastDirection)
--self.Animations:UpdateAnimationsFromStates(self.lastDirection, self.StateController:GetState())
if self.shiftLocked then
if self.lastDirection ~= self.currentDirection or self.lastState ~= self.currentState then
self.Animations:UpdateAnimations(self.currentDirection, self.StateController:GetState())
self.lastDirection = self.currentDirection
self.lastState = self.currentState
end
else --not in shift lock
if self.lastState ~= self.currentState then
self.Animations:UpdateAnimations(self.currentDirection, self.StateController:GetState())
self.lastState = self.currentState
end
end
--print(" ")
--print("state: " .. self.StateController:GetState())
--print("direction: " .. self.lastDirection)
--print(" ")
end
function MovementController:ToggleShiftLock()--self explanatory just tweens the camera when they go in shift lock
self.shiftLocked = not self.shiftLocked
if self.shiftLocked then
workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
local t = game:GetService("TweenService"):Create(self.Humanoid, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {CameraOffset = Vector3.new(0, 3, 0)}):Play()
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.LockCenter
else
workspace.CurrentCamera.CameraType = Enum.CameraType.Custom
local t = game:GetService("TweenService"):Create(self.Humanoid, TweenInfo.new(0.1, Enum.EasingStyle.Sine, Enum.EasingDirection.Out), {CameraOffset = Vector3.new(0, 0, 0)}):Play()
game:GetService("UserInputService").MouseBehavior = Enum.MouseBehavior.Default
end
end
return MovementController
The problem is, you can probably see that I’m trying to implement jumping but I don’t know how I would detect when the player jumps, when they land, etc since I’m calling update every frame. Is there a better way to do this where I’m not checking the state every frame? Am I overcomplicating this? I don’t think I’ll be able to add all of the movement that I want to add (jumping, dashing, wall running) using this current system.
Side note: You can still jump because I didn’t disable normal player jumping, I just have no way of detecting when the player jumps and lands
Another side note: I was thinking about making a custom jump function instead of using the Humanoid states to tell when the player jumps, but surely there is a less complicated way right?