Help getting player movement direction

I need a way to get the movement direction of the player and have it return a string such as: “Forward”, “Backward”, “DiagnalRight”, ect…

Insight to why

I am developing an RPG with a combat system similar shadow fight 2.
as you can see in this gif; it’s a 2d game with an 8-Directional movement system,
which is why I also need to know if the player is moving diagnaly.
ezgif-2-3b2664e009

The only post i’ve found on this was here which never found sulotion, and the code didn’t work for me. Furthermore, It doesn’t cover diagnal movement.

relevent code:

local ContextActionService = game:GetService("ContextActionService")

local player = game:GetService("Players").LocalPlayer
local MoveVector = require(player:WaitForChild("PlayerScripts").PlayerModule:WaitForChild("ControlModule"))

local function getMovement()
	local hrp = player.Character.HumanoidRootPart
	local movementDirection = workspace.CurrentCamera.CFrame:VectorToObjectSpace(player.Character.Humanoid.MoveDirection).Unit --not being used
	
	local lookVector = player.Character.Humanoid.MoveDirection:Dot(hrp.CFrame.LookVector)-- up down
	local rightVector = player.Character.Humanoid.MoveDirection:Dot(hrp.CFrame.RightVector)-- sides

	print(lookVector)
	print(rightVector)
	if lookVector > 0 then
		warn("Forward")
	elseif lookVector < 0 then 
warn"Backward"
	end
--haven't tried the left & right movement yet because this doesnt even work

end

PlayerMovment = {}

function PlayerMovment.setBattleMovement()
ContextActionService:BindAction("Gamepd", getMovement, false,
		Enum.UserInputType.Gamepad1, Enum.UserInputType.Touch
	)

end

return PlayerMovment

Thanks

What movement are you looking for?

Are you looking for raw player inputs (e.g. w, a, s, d, wa, wd, as, sd, but it also works for mobile), world relative movement directions, or character relative movement directions?


You can get a name for the direction a player is moving by using a Dot product to compare different directions.

For example:

local directions = {
    {Vector3.new(0,0,1), "Forward"},
    {Vector3.new(1,0,1).Unit, "ForwardRight"},
    {Vector3.new(1,0,0), "Right"},
    -- TODO: Fill out the other directions
}

local function getDirectionName(direction)
    direction = direction.Unit
    local maxDot = -1 * math.huge
    local maxName = ""
    for _, possibleDirectionPair in ipairs(directions) do
        -- Checks how similar the two directions are
        dot = direction:Dot(possibleDirectionPair[1])
        if dot > maxDot then
            maxDot = dot
            maxName = possibleDirectionPair[2]
        end
    end

    return maxName
end

You can then get the movement direction you’re looking for based on what you want:

  • You can get raw input directions from the PlayerModule (there are some topics on the forums for this)
  • You can get the world-relative direction the character is moving from Humanoid.MoveDirection
  • You can a character relative direction using HumanoidRootPart.CFrame:VectorToObjectSpace(Humanoid.MoveDirection)
1 Like

Thank you so much! This sulotion works for my needs, and is expadable. Only question I was wondering is what does .Unit do for the diagnals if you already get the unit in the function? During testing I found out that why but I dont understand how normalizing before the function changes it. Cheers!

1 Like

The dot product result depends on the length of the two vectors.

In the function, the input vector is normalized (set to a length of one).

However, for it to be a fair comparison between all the directions, all of those also have to be a length of one. That’s why I added the .Unit in the table, so that even the diagonals have a length of one (otherwise they’d have a length of root 2).


If you didn’t want to do that in the table, you could change this line:

dot = direction:Dot(possibleDirectionPair[1])

to

dot = direction:Dot(possibleDirectionPair[1].Unit)

so that all the directions being compared are unit (length 1) vectors.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.