Disclaimer: This tutorial assumes you know some trigonometry and basic physics.
Hey fellow Developers! Today, I’m writing this tutorial on a Simple Pendulum Model, which simulates the oscillation of a Pendulum in game.
So, I’m writing this because I want to see how much I’ve learnt while reading up on this topic and see if I can help anyone else to understand it in the simplest terms… I think this thread can help me test my knowledge, help others learn and give other more experienced developers an opportunity to leave feedback and tell me what I can do better etc.
So firstly, what is a pendulum? A pendulum is an object that has a:
An Arm(String, Rope…etc):
and a Fixed Point/Origin:
and how this works is
the Bob is suspended/connected to the fixed point by the arm.
so now that we know what a pendulum is and we’ve visualized it in basic terms, how do we simulate it in game?
Well, to do that we need to know what Pendulum Motion is, so we that can calculate it ingame:
So, the internet(yes the interweb, my favorite place for finding meanings) says that:
“Pendulum motion basically depicts the motion of an object(Bob) hanging from a string(Arm) that moves back and forth. The variables in pendulum motion are the mass, the length of the string, and the location, which is measured by an angle. Forces acting on the mass in pendulum motion are tension and gravity.”
Alright so we know what pendulum Motion is, how do we calculate it?
Well, the displacement of a Pendulum’s Bob is the length of the arc
as seen here:
Now we just need to find that Arc and have the bob travel along it, so let’s hop into some code
–// I’ll be using CFrames for this tutorial, If you can find the displacement
–// You can derive velocity from it yourself using the method I’m about to display
–// And from there you can use a BodyVelocity and constantly update the values
–// But anyways let’s get into it
First I create my Bob and Pendulum in the workspace
Please make sure both of these objects are anchored, remember we aren’t using
the physics engine, we’re manipulating their positions to recreate the Pendulum Motion
Then you create your script ( anywhere you want as long as it’s within a runtime environment)
--//Let's define our Bob and Origin Variables local Bob = workspace.Bob local Origin = workspace.Origin --//Next we get the Arm's length ( in this case the distance from the Origin to the Bob --//We don't use an actual rope constraint or anything else, we can use a beam for aesthetics local Length = (Origin.Position - Bob.Position).magnitude --//Okay alot of people may get confused by this part, but now we want a predefined --//Angle for the sake of this tutorial, so we'll go with an angle of 45 deg local theta = 45 --//Value for angular velocity which we will use later local angVel = 0 --//Next we create our function to compute the Bob's Motion per Oscillation local function Compute() --//Using Trigonometry we want to find the arc of the Bob's Displacement on each axis --//The reason we multiply the length by the the Arc is so that we take the Length of the arm --//Into account when returning the arc of the angle on the axis.. --//In simple terms, we're offsetting the arc from the origin point by the Length local XArc = Length * math.sin(theta) local YArc = Length * math.cos(theta) --//Okay so now we lerp the Bob's CFrame, WHILE keeping it relative to the Origin Point Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + Origin.CFrame.Position, 0.4) end --//To constantly update the CFrames and Values game.RunService.Heartbeat:Connect(Compute)
Okay for visualization purposes, I suggest you test the code ingame and see what happens, as you’ll see the Bob experiences displacement, but we want constant displacement, constant velocity, well how do we do that?
well, within our code we need to find the angular velocity and apply it to our angle, so let’s do that right now
local function Compute() local XArc = Length * math.sin(theta) local YArc = Length * math.cos(theta) Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + Origin.CFrame.Position, 0.4) --//Now, what's happening here is we're adding our previous angular velocity to a new arc that --//uses the same angle, but it experiences gravity (substituted by 0.01) angVel = (angVel + (0.01*math.sin(theta))) --//Now we apply our AngVel to our Angle and there we have it. theta = theta + angVel end
here’s our Pendulum in the works:
I apologize in advance if anyone was left confused by this post, I just learnt this and I wanted to share my knowledge with the community in hopes of helping anyone, I really hope someone learned a thing our two from this post.
If you want the Pendulum to return to Equilibrium, you can dampen it with the 0.99 value
local function Compute() local XArc = Length * math.sin(theta) local YArc = Length * math.cos(theta) Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + Origin.CFrame.Position, 0.4) angVel = (angVel + (0.01*math.sin(theta))) * 0.99 theta = theta + angVel end
Here is the Pendulum with a cool Spiderweb:
Also EgoMoose if you’re reading this, I’m a big fan of your work!