How to make a pendulum swing be according to the part's orientation

I made a pendulum swinging mechanism for the player by taking code off of this post and I managed to make it do this

But when I do it on a part rotated differently, it goes the same direction which I don’t want

I’m not really that good at trigonometry, so how do I make this pendulum involving the character swing according to the part’s orientation


		local Origin = raycast.Instance
		local Bob = hrp
		
		local Length = (Origin.Position - Bob.Position).Magnitude
		local theta = 45
		local angVel = 0
		local function Compute()
			local XArc = Length * math.sin(theta)
			local YArc = Length * math.cos(theta)
			--local ZArc = Length * math.rad(theta)
			
			Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + 
				Origin.CFrame.Position, 0.05)
			angVel = (angVel + (0.01*math.sin(theta)))
			theta = theta + angVel
		end
		deb = true
		local playerdirection = hrp.CFrame.LookVector
		if -playerdirection.Z > 0 then
			print(theta)
			theta = -theta 
		end
		conn = game:GetService("RunService").Heartbeat:Connect(Compute)
		task.wait(.8)
		hrp.Anchored = false
		deb = false
		if conn then
			conn:Disconnect()
		end
		rope:Destroy()
5 Likes

Bumping cause I still need help

1 Like

Not really part of the problem, but theta should be in radians using math.rad, not degrees since math.sin and math.cos accepts radians

2 Likes

Also, CFrame:Lerp accepts only two arguments, which is part.CFrame:Lerp(goal CFrame, alpha), not three (nvm, my bad, its correct)

Maybe try multiplying this with HumanoidRootPart.CFrame.LookVector?

Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) * (hrp.CFrame.LookVector * Vector3.new(1, 0, 1) + Vector3.new(0, 1, 0)), Vector3.new()) + 
				Origin.CFrame.Position, 0.05)
1 Like


Had some strange behaviour like going backwards and didn’t really seem to go the character’s direction he’s facing

You can flip the direction by adjusting the Vector3.new(1, 0, 1) to something like Vector3.new(-1, 0, -1) or Vector3.new(-1, 0, 1) or Vector3.new(1, 0, -1) to correct the backwardness (try all of them to see which one works, trial and error!)

Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) * (hrp.CFrame.LookVector * Vector3.new(-1, 0, -1) + Vector3.new(0, 1, 0)), Vector3.new()) + 
				Origin.CFrame.Position, 0.05)

Btw, sorry for the late response, I had to go sleep.

1 Like

It didn’t seem to work with the humanoid root part’s look vector so I changed it to the camera’s and that worked fine. I did Vector3.new(-2,0,-2) as my solution to fix the backwardness but I saw one really weird problem, it doesn’t go all the way for some certain rotations it seems:

I thought it was to do with the shorter sides of rectangles, but for some reason it doesn’t work on squares for one side too?

It fixed the main issue but I have no idea why the other one is happening and it’s not with the way the camera’s facing because if you face that same way for the other rectangle, it works just fine?

Maybe it’s to do with a certain axis of the part?

Here’s the code I used:

	Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) * (workspace.CurrentCamera.CFrame.LookVector * Vector3.new(-2, 0, -2) + Vector3.new(0,1,0)), Vector3.new()) + 
				Origin.CFrame.Position, 0.05)

It doesn’t seem to factor in the orientation it seems, but I have no idea how I would make it do that without breaking the code as lerp needs the position.

Can somebody please help me with this

Maybe you could try adding Vector3.Unit like this:

Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) * ((workspace.CurrentCamera.CFrame.LookVector * Vector3.new(-2, 0, -2)).Unit + Vector3.new(0,1,0)), Vector3.new()) + 
				Origin.CFrame.Position, 0.05)

It could be because the LookVector is looking too high (Thus Y is larger than X and Z), so by doing (workspace.CurrentCamera.CFrame.LookVector * Vector3.new(-2, 0, -2)).Unit, we are basically compensating for the loss of Y value since we remove it with the 0 in the 2nd Vector3.

Vector3.Unit basically normalizes the Vector3 and make it has a magnitude of 1. So, Vector3.new(0.5, 0, 0.5).Unit would give us Vector3.new(0.707..., 0, 0.707...).

Using Vector3.Unit is like how your character still walk with the same speed when looking up at a high angle. But without it, you will slow down, thanks to Y for taking up most of the Camera LookVector’s magnitude.

Also, try doing it with -1, 0, -1 to see if it works fine because I only intended to use that 2nd Vector for switching the direction, not increasing the intensity of it. But, if -2, 0, -2 works more correctly for some reason then I guess you can use it.

Bob.CFrame = Bob.CFrame:Lerp(CFrame.new(Vector3.new(XArc , YArc, 0) * ((workspace.CurrentCamera.CFrame.LookVector * Vector3.new(-1, 0, -1)).Unit + Vector3.new(0,1,0)), Vector3.new()) + 
				Origin.CFrame.Position, 0.05)

PS: Sorry for leaving you for a day :sweat_smile: I was busy with some stuffs. Also, you asked for the character’s direction, that’s why I used the hrp LookVector instead of the camera.

I think this is the cframe you’re moving the character to during the swing:

CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + Origin.CFrame.Position

You could try something like this, it should rotate your CFrame around the center of the part based on the rotation of the part.

local cframe = CFrame.new(Vector3.new(XArc , YArc, 0) , Vector3.new()) + Origin.CFrame.Position

-- (cframe rotation) * part rotation + position
local relative = (cframe - cframe.Position) * (Origin.CFrame - Origin.Position) + cframe.Position
-- Now use the relative cframe in place of the old one