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

4 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 :slight_smile:

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”.