Help with CFrame + Rotation math for pet movement

There is something I have been struggling for quite a bit now. This is a script that manages the pet(s) following the player if it is equipped. The pet’s movement (before) was quite plain and looked like this-
https://gyazo.com/aa7178ce456efdf97b60b82ec6793c71

local Disabled = false
local Player = game.Players:FindFirstChild(script.Parent.Parent.Name)

if Player then
	while wait() do
		if Player.Character.Health ~= 0 then
			if not Disabled then
				local Pos = script.Parent.Pos.Value
				local BG = script.Parent.PrimaryPart.BodyGyro
				local BP = script.Parent.PrimaryPart.BodyPosition
				local d = Player.Character.HumanoidRootPart.Position.Y - script.Parent.PrimaryPart.Position.Y
				BP.Position = (Player.Character.HumanoidRootPart.Position + Pos) - Vector3.new(0,Player.Character.HumanoidRootPart.Size.Y/2,0) + Vector3.new(0,script.Parent.PrimaryPart.Size.Y/2,0) + Vector3.new(0,game.ServerScriptService.Pets.globalPetFloat.Value,0)
				if Player.Data.isWalking.Value == false then
					BG.CFrame = CFrame.new(script.Parent.PrimaryPart.Position, Player.Character.HumanoidRootPart.Position - Vector3.new(0, d, 0))
				else
					BG.CFrame = Player.Character.HumanoidRootPart.CFrame
				end
			else
				script.Parent:Destroy()
				break
			end
		else
			Disabled = false
		end
	end
end

So I added on to the code and this is what I have at the moment-
https://gyazo.com/09c43a41f9dd64f1e7d7f482fe408c18

local Disabled = false
local Player = game.Players:FindFirstChild(script.Parent.Parent.Name)
local angle = 180

wait(.001)
if Player then
	while wait(0.025) do
		if angle >= 360 then
			angle = 0
		end
		angle += 6
		if Player.Character.Health ~= 0 then
			if not Disabled then
				local Pos = script.Parent.Pos.Value
				local BG = script.Parent.PrimaryPart.BodyGyro
				local BP = script.Parent.PrimaryPart.BodyPosition
				local d = Player.Character.HumanoidRootPart.Position.Y - script.Parent.PrimaryPart.Position.Y
				BP.Position = (Player.Character.HumanoidRootPart.Position + Pos) - Vector3.new(0,Player.Character.HumanoidRootPart.Size.Y/2,0) + Vector3.new(0,script.Parent.PrimaryPart.Size.Y/2,0) + Vector3.new(0,game.ServerScriptService.Pets.globalPetFloat.Value,0)
				if Player.Data.isWalking.Value == false then
					BG.CFrame = CFrame.new(script.Parent.PrimaryPart.Position, Player.Character.HumanoidRootPart.Position - Vector3.new(0, d, 0)) + Vector3.new(0, math.sin(math.rad(angle)), 0))
				else
					BG.CFrame = Player.Character.HumanoidRootPart.CFrame + Vector3.new(0, math.sin(math.rad(angle)), 0)
				end
			else
				script.Parent:Destroy()
				break
			end
		else
			Disabled = false
		end
	end
end

I added the angle thing which makes it sort of look like Bubble Gum Simulator pets’ movement
https://gyazo.com/77b60bdd3d63e0029e9777ccb56b1cf9
__
My problem is that the addition I made only works when the player is idle or ‘isWalking = false’
I need help with figuring out how to make it do that swing/rotation while the player is walking but at the same time following the player + looking at the direction player is walking.
https://gyazo.com/fc6c59acb1b950ddba6622928b37bb13
Any help is appreciated!
Thank you for reading!

1 Like

I think this should be doable just with a premultiplication with an appropriate CFrame.

It might be as simple as: CFrame.Angles(angle, 0,0) * ( rootPart.CFrame + vector )

1 Like

BodyGyro ignores the positional properties of the CFrame and only looks at the angular portion. I believe the reason it’s not doing anything when you walk is because the code

BG.CFrame = Player.Character.HumanoidRootPart.CFrame + Vector3.new(0, math.sin(math.rad(angle)), 0)

is not doing any angular translations. The angles are getting chosen from the character’s HumanoidRootPart CFrame. You are then doing a positional translation on the HumanoidRootPart CFrame and setting it to the BodyGyro CFrame, but that change is completely ignored.


Quick important side note: The line of code in the isWalking == false part is working as you intend visually, but I actually think it’s not working as you think it does internally. What the code

CFrame.new(script.Parent.PrimaryPart.Position, Player.Character.HumanoidRootPart.Position - Vector3.new(0, d, 0)) + Vector3.new(0, math.sin(math.rad(angle)), 0))

does is construct a CFrame originating at the first argument but angled towards looking at the second argument (see 3rd constructor on this page). Both of these are positions (not angles).

Your “Vector3.new(0, math.sin(math.rad(angle)), 0)” addition is actually just making the pet point towards a position slightly above the player measured in radians (this should be in studs actually). This is probably not what you meant to really do, I’m guessing.

I was a bit confused at first since your code looks like the pet should rotate 360 degrees which it doesn’t in the GIF. This is because you are converting to radians and doing a positional look-at translation with that (which would go from 0 to 2*PI or 0 to 6.28 studs).


One solution to fix the isWalking == true section would be to keep the original BG.CFrame math in the original code, but you need to do an angular translation on it for the bobbing effect (remember you were doing positional before). To do this, you need to use CFrame.Angles() which returns a rotated CFrame (found on this page). You can then multiply this rotated CFrame by the other CFrame to do an angular translation.

This is not tested (I might have got the axis wrong), you might have to play around with it, but I think it would be something like this:

BG.CFrame = Player.Character.HumanoidRootPart.CFrame * CFrame.Angles(0, math.rad(angle), 0)

You could do something similar for the code that was working in the isWalking == false, as well:

BG.CFrame = CFrame.new(script.Parent.PrimaryPart.Position, Player.Character.HumanoidRootPart.Position - Vector3.new(0, d, 0)) * CFrame.Angles(0, math.rad(angle), 0)

These code changes might make the pet spin dramatically, in which case you need to modify how much your angles are moving (not 360 degrees).

Hope this was helpful in some way!

2 Likes

Thank you a million! I really appreciate it, I hope you have a great day!!

1 Like