Math behind bodygyro?

I’m trying to create similar functionality to a BodyGyro using other forces but I can’t seem to find any documentation on how the force applied is actually calculated. Now I know the P/d formulas for the BodyPosition object can be very easily found but I haven’t seen any other forum posts similarly for BodyGyro’s. The reason I want to do this is I want to calculate and allow/disallow rotation around an inclined plane rather than just either the X, Y, or Z planes. Any pointers would be great! Thanks.

2 Likes

BodyPosition seems to take the difference between the part’s current position and the target position, then attempt to reduce the difference by applying Velocity to the part.
I’d imagine BodyGyro takes the difference between the part’s current orientation and the target orientation, then attempts to reduce the difference by applying RotVelocity.
Try looking for how CFrame lerping is done, that’ll tell you how to get the difference between two orientations.

I’m looking more for an explanation on how they implement their PID controllers. But thanks!

Micha,
Or anybody…

Could you give a link to these formulas, of which you speak,

I want my Insectoid to work on any planet, and my game-leader went and changed Gravity…

I have Gyro down: Stick any convienient CFrame into it, aND DON’T WORRY ABOUT the .Position bit, which is ignored…
Why don’t you want to use Gyro?

You can use this on slopes, but you can’t go up-side-down (Which I would also need…)
The CFrame(Origin, PositionToLookAt) works as input on a flat Earth… Just put the Position out in front of the Model in the Direction you want to face…

YOU HAVE Formulas…So I don’t have to trial and error, BodyPosition…?

In trade:
I will give you a half finished Insectoid script which walks up and down walls; instead of around them… Several Gyro fudges in here for you to canabalize…

bin = script.Parent

local Players = game:GetService(“Players”)

local humanoid = bin.Parent.Humanoid
local HipHeight = .9 – Not used yet: An absolute, relative to what the spider is standing on…
local HIPHEIGHT = .9
local TORQUE = 2

local RootPart = bin.Parent:WaitForChild(“HumanoidRootPart”) – sAME AS BIN ACTUALY…

– Turn into loose body:
humanoid:ChangeState(Enum.HumanoidStateType.Physics)

local Gyro = bin:WaitForChild(“BodyGyro”)
Gyro.cframe = bin.CFrame
Gyro.maxTorque = Vector3.new(10000,10000,10000) * TORQUE

local BodyPos = bin:WaitForChild(“BodyPosition”)
BodyPos.Position = bin.Position
BodyPos.maxForce = Vector3.new(10000,10000,10000) * bin.Speed.Value

local Logic = 0 --How far from an orbit are we?

function DrawRay(origin, direction) – origin is a point. Direction is a vector3; it’s magnitude = length
local hitPart
local Position = origin + direction – Destination position, unless hit a part
local Normal

local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {bin.Parent} -- whatever model this is in...
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist -- don't hit any parts of us

local raycastResult = workspace:Raycast(origin, direction, raycastParams)

if raycastResult then
	hitPart = raycastResult.Instance
	Position = raycastResult.Position
	Normal = raycastResult.Normal

print(“Normal”, Normal)
end

if true then --Graphics for debugging
	local RayPart = Instance.new("Part", bin.Parent)
	if hitPart then -- Black if hit something
		if true then -- You can check which call this cast is for and change the color
			RayPart.BrickColor = BrickColor.new("Black") --Set its color.
		else
			RayPart.BrickColor = BrickColor.new("Bright red") --Set its color.
		end
	else -- White color if no hit
		if true then
			RayPart.BrickColor = BrickColor.new("White") --Set its color.
		else
			RayPart.BrickColor = BrickColor.new("Olive") --Set its color.
		end
	end
	RayPart.Transparency = 0.3 --Set its transparency.
	RayPart.Anchored = true --Set whether it will fall or not.
	RayPart.CanCollide = false --Set whether people can walk though it or not.	
	RayPart.formFactor = Enum.FormFactor.Custom --Make it so it can be small.
	
	local Distance = (Position-origin).magnitude --Find the distance between the hit and the torso.
	local PercentLeft = 3*(1-Distance/(direction).magnitude)+0.3 -- What percentage of direction did we not make X 3

	RayPart.Size = Vector3.new(.4, PercentLeft,Distance) --Set its size to the distance.
	RayPart.CFrame = CFrame.new(Position, origin) * CFrame.new(0,0,-Distance/2) --Move it halfway.
	game.Debris:AddItem(RayPart,5) --Add it to the debris.
end -- Graphics
return hitPart, Position, Normal

end

–Set Hip Height for Humanoid
wait(1)
–while RootPart.AssemblyLinearVelocity.y < -.01 do
–print( RootPart.AssemblyLinearVelocity.y)
– wait(1)
–end

–do
– local dir = bin.CFrame.UpVector * -5
– local Hit, Position = DrawRay(bin.Position, dir)
–print(dir, Hit, Position)
– if Hit then
– local H = RootPart.position.y - Position.y
– humanoid.HipHeight = H + 0.1
–print(“Hip Height for Spider is”, H)
– else
–print(“Please, set Spider on a surface”)
– end
–end – set hip

function move(target) – Aim – At a .Position
Gyro.cframe = CFrame.new(bin.Position, target)
end
– bin:findFirstChild(“BodyGyro”).cframe = CFrame.new(spawnPos, target)
– bin:findFirstChild(“BodyGyro”).maxTorque = Vector3.new(19000,19000,19000)

function moveTo(target)
BodyPos.Position = target
– bin.BodyPosition.maxForce = Vector3.new(10000,10,10000) * bin.Speed.Value
end

function findNearestTorso(pos)
local list = game.Workspace:GetChildren()
local torso = nil
local dist = 100
local temp = nil
local human = nil
local temp2 = nil
for x = 1, #list do
temp2 = list[x]
if (temp2.className == “Model”) and (temp2 ~= script.Parent) then
temp = temp2:findFirstChild(“Head”)
– temp = temp2:findFirstChild(“HumanoidRootPart”)
human = temp2:findFirstChild(“Humanoid”)
if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
if (temp.Position - pos).magnitude < dist then
torso = temp
dist = (temp.Position - pos).magnitude
end
end
end
end
return torso
end

local players = Players:GetPlayers()
for i, player in pairs (players) do
if player.Character then
if player.Character:FindFirstChild(“HumanoidRootPart”) then
–check for magnitude here
end
end
end

function GetNormal(N) – Square-up to a Normal
move(bin.Position - N)
wait(.1)
end

local UP = Vector3.new(0,6,0)
local DOWN = Vector3.new(0,-6,0)

function ComeBackToLevel(Logic) – Climb Obsticals until reaching a flat level state…
local Facing = bin.CFrame – old position
local Looking = Facing.LookVector

if Logic == 1 then
	local dir = (Facing + UP + Looking).Position

–Aim
move(dir) – Face up in the dir we r facing
–turn up
wait(.1)
– start moving up
moveTo(dir)
wait(.1)

–keep moving up
repeat
–print(bin.position.y)
dir = (bin.position + bin.CFrame.LookVector * 6) – Spider is hopefully looking up
moveTo(dir)
wait(.2)

		if not DrawRay(bin.Position, bin.CFrame.UpVector * -5) then -- Check if we are still on a wall
			Logic = 0
		end
	until Logic ~= 1

end -- Logic up?

–Climb down
if Logic == -1 then
local dir = (Facing + DOWN + Looking).Position
–Aim
move(dir) – Face down in the dir we r facing
–turn DOWN
wait(.1)
– start moving DOWN
moveTo(dir)
wait(.1)

	--keep moving down
	repeat
		--print(bin.position.y)
		dir = (bin.position + bin.CFrame.LookVector * 9) -- Spider is hopefully looking down
		moveTo(dir)
		wait(.2)
		if DrawRay(bin.Position, bin.CFrame.LookVector * 5) then -- Check if a floor is ahead
			Logic = 0
		end -- floor?

print(“Logic”, Logic)
until Logic ~= -1

end -- Logic down?

– Reset
Gyro.cframe = Facing – reset
wait(.1)
end – Climb until level again

– Main

while true do
local torso = findNearestTorso(bin.Position)
local hit = nil – What Part ray hit
local RayPos – Position Where it hit part

–Player?
if torso~=nil then
local dir = (bin.CFrame.LookVector) * 5 – Ray to check for wall in front
– Wall?
hit, RayPos, Normal = DrawRay(bin.Position, dir)
if hit then
GetNormal(Normal) – Line up perpendicular to wall
Logic = 1
ComeBackToLevel(Logic)
elseif not DrawRay(bin.Position, bin.CFrame.UpVector * -5) then
Logic = -1
ComeBackToLevel(Logic)
end
–Aim
move(Vector3.new(torso.Position.x, bin.position.y, torso.Position.z)) – Toward Player but at spider’s height

–floor?
dir = (bin.CFrame.UpVector) * -199 – Ray to check for hip height
hit, RayPos = DrawRay(bin.Position, dir)

	dir = (bin.CFrame + bin.CFrame.LookVector * 9).Position
	if hit then		
		dir = Vector3.new(dir.x, RayPos.y + HIPHEIGHT, dir.z) -- direction we are aiming + hipheight
	end

–Move toward aim
moveTo(dir)

end

-- Go!	
wait(.2)

end