3D Pendulum Script

With this code I have created a pendulum that works along the X and Y axis, how would I go about making this work for the Z axis as well?

local Bob = workspace.Bob
local Origin = workspace.Origin

local Length = (Origin.Position - Bob.Position).Magnitude
local theta = math.rad(45)
local aVelocity = math.rad(5)

game["Run Service"].Heartbeat:Connect(function(dT)
	theta = theta + aVelocity
	
	local XArc = Length * math.sin(theta)
	local YArc = Length * math.cos(theta)
	
	Bob.Position = Origin.Position + Vector3.new(XArc, -YArc, 0)
end)

I’m not really too great with trigonometry but surely you’d use tangent to get the Z axis?

local ZArc = Length * math.tan(theta)

By “working on the Z axis” do you mean you want it to work regardless of how the object is oriented?

My advice would be to use CFrame instead of Position:

...
    Bob.CFrame = Origin.CFrame * CFrame.new(XArc, -YArc, 0)
...
1 Like

Have you confused a pendulum with orbiting? Because what your code produces is object ‘Bob’ orbiting around object ‘Origin’ in a full circle.

A pendulum is essentially a swinging object which moves side to side. What you should use here is a sine wave which you give tick() as an argument to provide a continuous range from -1 to 1.

From this, you can continuously update Bob’s CFrame using Origin’s position, taking into account the origin’s rotation as well and applying an offset which is half the length of the pendulum.

game:GetService("RunService").Heartbeat:Connect(function()
local swing = math.sin(tick())

Bob.CFrame = (CFrame.new(Origin.Position) * CFrame.Angles(0, math.rad(Origin.Orientation.Y), swing) * CFrame.new(0, -Bob.Size.Y/2, 0))	
end)

This produces the following as a result and allows for rotating the origin and updating accordingly:

https://gyazo.com/8a59dab3aaa371abdd483193acbab233

10 Likes

thanks, that is the type of behavior I am looking for.

Another question: how would I increase the range and allow the bob to swing to higher positions?

Apply a multiplier to the sine wave. For example if you double it, you’ll notice it will swing much higher.

local swing = math.sin(tick()) * 2
2 Likes