Orienting controls relative to rotation

So I am trying to make it so that the player is perpendicular to a sphere and can walk around it. So far the orbiting works (gravitational force with non euler integration) however aligning, not so much. I am using quaternions to align it. I don’t really understand what it does other than align 2 vectors together. It works okay if I am going along a certain direction however the same problem still persists. Roblox is applying forces to move on 1 world axis and is not changing it dependent on the players rotation. Any ideas on how to fix this? My code

local function getMass(char)
	local mass = 0
	for _, v in pairs(char:GetDescendants()) do
		if v:IsA("BasePart") then
			mass += v:GetMass()
		end
	end
	return mass
end

local function getClosestFaux(char, fauxs)
	local closest = 0
	local faux = nil
	for i, v in pairs(fauxs:GetChildren()) do
		if v:IsA("BasePart") then
			local dif = (v.Position - char.HumanoidRootPart.Position).Magnitude
			if dif > closest then
				closest = dif
				faux = v
			end
		end
	end
	return closest, faux, faux:GetMass()
end

local function getScalar(char)
	local m1 = getMass(char)
	local difference, faux, m2 = getClosestFaux(char, workspace.Fauxs)
	return m1 * m2 / difference^2, faux, difference
end

local function getNormal(char, faux)
	return (faux.Position - char.HumanoidRootPart.Position).Unit
end

local function getRotationBetween(u, v, axis)
	local dot, uxv = u:Dot(v), u:Cross(v)
	if (dot < -0.99999) then return CFrame.fromAxisAngle(axis, math.pi) end
	return CFrame.new(0,0,0, uxv.x, uxv.y, uxv.z, 1 + dot)
end


game.Players.PlayerAdded:Connect(function(plr)
	plr.CharacterAdded:Connect(function(char)
	char.Humanoid.PlatformStand = false
	local attractor = script.attractor:Clone()
	attractor.Parent = char.HumanoidRootPart
	game:GetService("RunService").Heartbeat:Connect(function()
		local scalar, faux, difference = getScalar(char)
		local normal = getNormal(char, faux)
		local force = scalar * normal
		attractor.Force = force
		local u = char.HumanoidRootPart.CFrame.UpVector
			local axis = u:Cross(normal)
			char.LowerTorso.Root.C0 = CFrame.new(0,-1,0,1,0,0,0,1,0,0,0,1) * getRotationBetween(u, -normal, axis)
		end)
	end)
end)

[fauxGravity.rbxl|attachment]

(upload://O8Qt9k4p90Ckci2WsSZzV8zhiM.rbxl) (22.3 KB)

1 Like

You can transform the normal to the HumanoidRootPart’s rotation like so:

local normal = getNormal(char, faux)
normal = char.HumanoidRootPart.CFrame:VectorToObjectSpace(normal)

Here’s a video of what the result looks like

Thanks that worked. But can you expand on what VectorToObjectSpace really does? I don’t really understand this concept of transforming normals to a rotation

Sorry, I’m not really good at explaining stuff, but basically the normal is a vector in world space, and VectorToObjectSpace sorta shifts the world space orientation to match whatever CFrame you call :VectorToObjectSpace on. Sorry if that doesn’t make much sense, maybe someone else can provide a more elaborate explanation… Here is the wiki’s explanation and the formula they use:image

VectorToObjectSpace takes in a vector as an argument and returns that vector rotated to match the rotation of the CFrame in world space.

1 Like