# Rounding a lookvector to the nearest axis?

I want to set a bodyforce in the direction of a lookvector, but I want it to be rounded to one axis.

so for example, if the lookvector is closest to pointing up, I want to set the bodyforce’s Y axis to start pushing in that direction and not any other, the code here should help you understand what im trying to do:

``````local forcenum = 1000000
local lv = char.HumanoidRootPart.CFrame.LookVector * 100000
local origin = char.HumanoidRootPart.Position
local direction = Vector3.new(0,0,0)
if lv.Y > origin.Y then
direction = Vector3.new(0,forcenum,0)
elseif lv.Y < origin.Y then
direction = Vector3.new(0,-forcenum,0)
elseif lv.X > origin.X then
direction = Vector3.new(forcenum,0,0)
elseif lv.X < origin.X then
direction = Vector3.new(-forcenum,0,0)
elseif lv.Z > origin.Z then
direction = Vector3.new(0,0,forcenum)
elseif lv.Z < origin.Z then
direction = Vector3.new(0,0,-forcenum)
end
``````

however the problem with this is that if the lookvector is also bigger than x as well as y, it will pick the incorrect direction.

what do I add to get it to pick the closest axis?

3 Likes
``````-- Round the number to the nearest base
function round(num, base)
return math.floor(num/base+0.5)*base
end

-- Round the vector components (x,y,z) to the nearest base
function roundVec3(vec, base)
return Vector3.new(round(vec.X, base), round(vec.Y, base), round(vec.Z, base))
end

-- Align the vector to the global axis by rounding it's components to 1
function alignVec3ToAxis(vec)
return roundVec3(vec, 1)
end
``````

I think that’s what you need?!

I don’t think that’s quite right, since e.g. Vector3.new(.707, 0, .707) would become (1, 0, 1), which is not an axis.

1 Like

so theres 3 functions, do I use all three? im a bit confused as to which one I need.

1 Like

You need the third one. Just pass your lookVector like this:
local resultVector = alignVec3ToAxis(LookVector)

The first 2 functions are needed by the last one. however this solution also supports diagonal axis as @nicemike40 stated.

I think something like this would work for +/-XYZ axes:

``````function SnapToAxis(vec)
local lx = math.abs(vec.X)
local ly = math.abs(vec.Y)
local lz = math.abs(vec.Z)

if (lx > ly and lx > lz) then
return Vector3.new(math.sign(vec.X), 0, 0);
elseif (ly > lx and ly > lz) then
return Vector3.new(0, math.sign(vec.Y), 0);
else
return Vector3.new(0, 0, math.sign(vec.Z));
end
end

-- usage e.g.

local lv = ....CFrame.LookVector

local axis = SnapToAxis(lv);
``````

edit: replace old `sign` with new `math.sign`

3 Likes

I think there should be a more efficient way of implementing this, at least i hope so lol !

your first local function is throwing an error stating it needs an end to close the if statements.

and also llyas, I tried yours but the returned vector wasnt one specific vector, it printed numbers on all 3 axises

1 Like

True, but I’m sure you could do that It’s got a few more typos as well now that I look at it. Gimme a sec.

2 Likes

OK, fixed. Still not tested but better lol

1 Like
``````local function sign(x)
if (x == 0) then return 0;end
if (x > 0) then return 1;end
return -1;
end

function SnapToAxis(vec)
local lx = math.abs(vec.X)
local ly = math.abs(vec.Y)
local lz = math.abs(vec.Z)

if (lx > ly and lx > lz) then
return Vector3.new(sign(vec.X), 0, 0);
elseif (ly > lx and ly > lz) then
return Vector3.new(0, sign(vec.Y), 0);
else
return Vector3.new(0, 0, sign(vec.Z));
end
end

-- usage e.g.

local lv = ....Cframe.LookVector

local axis = SnapToAxis(lv);
``````

I added the ends to silence the errors there, but the line with “…CFrame.LookVector” is stating:
"expected identifier when parsing expression got “.” "
why are there 4 dots to begin with?

I did reshape the code however:

``````local function sign(x)
if x == 0 then
return 0
end
if x > 0 then
return 1
end
return -1
end

function SnapToAxis(vec)
local lx = math.abs(vec.X)
local ly = math.abs(vec.Y)
local lz = math.abs(vec.Z)

if (lx > ly and lx > lz) then
return Vector3.new(sign(vec.X), 0, 0)
elseif (ly > lx and ly > lz) then
return Vector3.new(0, sign(vec.Y), 0)
else
return Vector3.new(0, 0, sign(vec.Z))
end
end
``````

and this now returns what I need.

The last two lines were me showing you how to use the function. The `...` part was meant to imply “fill this out with however you plan on getting the lookvector”.