Trying to optimize if statement

hello, im trying to optimize this script because im using 9 if statement to get the direction where the player is heading

here :

local degree = 0.9

game["Run Service"].RenderStepped:Connect(function()
    local MoveDirection = humanoidrootpart.CFrame:VectorToObjectSpace(humanoid.MoveDirection)
					
	if MoveDirection:Dot(Vector3.new(1,0,-1).Unit) > degree then
		print("Forwards-Right")
	elseif MoveDirection:Dot(Vector3.new(1,0,1).Unit) > degree then
		print("Backwards-Right")
	elseif MoveDirection:Dot(Vector3.new(-1,0,1).Unit) > degree then
		print("Backwards-Left")
	elseif MoveDirection:Dot(Vector3.new(-1,0,-1).Unit) > degree then
		print("Forwards-Left")
	elseif MoveDirection:Dot(Vector3.new(0,0,-1).Unit) > degree then
		print("Forwards")
	elseif MoveDirection:Dot(Vector3.new(1,0,0).Unit) > degree then
		print("Right")
	elseif MoveDirection:Dot(Vector3.new(0,0,1).Unit) > degree then
		print("Backwards")
	elseif MoveDirection:Dot(Vector3.new(-1,0,0).Unit) > degree then
		print("Left")
	elseif MoveDirection == Vector3.new(0, 0, 0) then
		print("None")
	end
end)

I already tried with a table but the movedirection isn’t a vector3 with precise number
here

local directiontable = {
		{Vector3.new(1,0,-1), "Forwards-Right"},
		{Vector3.new(1,0,1), "Backwards-Right"},
		{Vector3.new(-1,0,1), "Backwards-Left"},
		{Vector3.new(-1,0,-1), "Forwards-Left"},
		{Vector3.new(0,0,-1), "Forwards"},
		{Vector3.new(1,0,0), "Right"},
		{Vector3.new(0,0,1), "Backwards"},
		{Vector3.new(-1,0,0), "Left"},
		{Vector3.new(0,0,0), "None"},
	}

-- these lines are in a renderstepped
local current = table.find(directiontable, MoveDirection)
if current and MoveDirection:Dot(current) > dotThreshold then
	print(current)
end

you could do this, so it only runs the if statements if the direction has actually changed

local lastMoveDirection = Vector3.new(0,0,0)

game["Run Service"].RenderStepped:Connect(function()
    local MoveDirection = humanoidrootpart.CFrame:VectorToObjectSpace(humanoid.MoveDirection)
					
    if MoveDirection ~= lastMoveDirection then
        lastMoveDirection = MoveDirection

        if MoveDirection:Dot(Vector3.new(1,0,-1).Unit) > degree then
            print("Forwards-Right")
        elseif MoveDirection:Dot(Vector3.new(1,0,1).Unit) > degree then
            print("Backwards-Right")
        elseif MoveDirection:Dot(Vector3.new(-1,0,1).Unit) > degree then
            print("Backwards-Left")
        elseif MoveDirection:Dot(Vector3.new(-1,0,-1).Unit) > degree then
            print("Forwards-Left")
        elseif MoveDirection:Dot(Vector3.new(0,0,-1).Unit) > degree then
            print("Forwards")
        elseif MoveDirection:Dot(Vector3.new(1,0,0).Unit) > degree then
            print("Right")
        elseif MoveDirection:Dot(Vector3.new(0,0,1).Unit) > degree then
            print("Backwards")
        elseif MoveDirection:Dot(Vector3.new(-1,0,0).Unit) > degree then
            print("Left")
        elseif MoveDirection == Vector3.new(0, 0, 0) then
            print("None")
        end
    end
end)

if you dont need this script to run every single frame then you could add a task.wait to slow it down a tad, which will also help optimize it slightly

1 Like

i didn’t think about this, maybe i can use it but its still unpratical, i need to do it for every players character, and i don’t think its a good idea if like 10 players stop walking at same time and the client has to pass theses statement

just a quick edit, movedirection isn’t really that precise

Not many know this, but renderstepped needs to be used with caution.

Roblox states that it actually can impact FPS quite alot, it’s recommended to be used as less as possible:

Movedirection is a property of the humanoid, so simply use a getpropertychangedsignal event.

humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
ocal MoveDirection = humanoidrootpart.CFrame:VectorToObjectSpace(humanoid.MoveDirection)
					
	if MoveDirection:Dot(Vector3.new(1,0,-1).Unit) > degree then
		print("Forwards-Right")
	elseif MoveDirection:Dot(Vector3.new(1,0,1).Unit) > degree then
		print("Backwards-Right")
	elseif MoveDirection:Dot(Vector3.new(-1,0,1).Unit) > degree then
		print("Backwards-Left")
	elseif MoveDirection:Dot(Vector3.new(-1,0,-1).Unit) > degree then
		print("Forwards-Left")
	elseif MoveDirection:Dot(Vector3.new(0,0,-1).Unit) > degree then
		print("Forwards")
	elseif MoveDirection:Dot(Vector3.new(1,0,0).Unit) > degree then
		print("Right")
	elseif MoveDirection:Dot(Vector3.new(0,0,1).Unit) > degree then
		print("Backwards")
	elseif MoveDirection:Dot(Vector3.new(-1,0,0).Unit) > degree then
		print("Left")
	elseif MoveDirection == Vector3.new(0, 0, 0) then
		print("None")
	end
end)

This is probably the most optimized solution you can get.

i just tested, uhm its does less but still to much it think

I didn’t read your original topic fully, if you want the direction the player is looking in you can use the lookvector/CFrame of the player’s head. Which is more accurate, and use it in that event thing I was saying.

You could try a dictionary with the directions:

local directions = {
    ["Forwards-Right"] = Vector3.new(1, 0, -1).Unit
    --etc.
}

--then...
local function onMoveDirectionChanged()
    local direction: nil

    for baseDirection: string, unit: number in next, directions, nil do
        if unit > degree then
            direction = baseDirection :: string
            break
        end
    end
end

Humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(onMoveDirectionChanged)

but yeah like @Amritss said you should probably use the HumanoidRootPart or Head’s LookVector property, especially considering MoveDirection will be set to Vector3.zero when the player is not moving.

I would say use the lookvector only if you’re forced to, a lookvector is a unit vector so it can be kinda hard to use. Whereas, CFrames contain both pos/orientation and are overall easier to use.

For example, I would need to use lookvectors if I wanted to make a dash ability with body velocity/applyimpulse method since I can only use vectors and not CFrames…

To be honest, there are multiple ways to do it. Having the main CFrame or the position in general would be helpful if trying to calculate it relative to the player, but a LookVector of the CFrame would be overall easier. The only other method using CFrames without the Lookvector I can think really think of is using it’s Euler Angles, but even then I think it would be better to compare the LookVector relative to the player.

I don’t really see the issue with using the LookVector, considering it just points to what direction the CFrane is facing in. You’d likely be using a similar system (and end up with an almost identical end result) to calculate what way the player is facing if you used the other CFrame properties and methods. Could you explain further?

Personally I just find lookvectors overall harder to use.

For example, CFrames can be used to move the player’s character in a :Fly command script which is what I did to make it. Rather than using lookvectors.

Plus, CFrames contain alot more things than lookvectors alone.

But obviously, there are times when one are harder to use than the other. From me alone though, I’ve struggled to use lookvectors more than CFrames.

But there are times when you need to use lookvectors, for example in a body dash system where you need to use a mechanical constraint such as body velocity possibly. The .Velocity property only allows vectors to be used and not CFrames.

From the context OP has provided, I believe he just wants information of the direction the player is facing and not to do much with it. Therefore, CFrames may be a good option as they contain alot more info than just a lookvector.

Instead of one or the other, it may be better to combine both, like I said in my previous post. (lol we basically are just using CFrames because LookVector is a property of it i forgot about that)

For example, the LookVector is just what direction the CFrame is facing in, so like you said, it doesn’t contain enough information.

But, we could use the CFrame’s Position (or just the Position property) to help us calculate the direction relative to the player. If we calculated general directions and aligned them with the position, we could compare them with the LookVector to calculate which one the player is closest to looking in.

I don’t really think there’d be a way to only use the LookVector or only use the other CFrame properties and methods, combining them seems like a sufficient method.

i think i’ll use that, no worry the player is not going to get a lot of loop trust

out of joke, itsn,'t a mid idea to loop it in a i,v loop

1 Like