CFrame Calculation Help

Hello!

INTRODUCTION
For the past day, I’ve been working on a small CFrame project. The project include a missile launcher of 2 parts. The base itself which rotates in the X axis and the launcher itself which rotates in the Y axis. The goal is to make both parts rotate and follow the mouse position and I have achieved that.

PROBLEM
After making the launcher follow the base’s rotation (X), the whole thing now rotates in both X and Y axis. Now, this is where I run into the problem. For some reason, the launcher started rotating in the Z axis by 1-10 degrees depending on the mouse position. I have already double checked my math and the math doesn’t even involve calculating the z axis. If you could help me on this, that’d be great thanks!

https://gyazo.com/77753e5f5d7601c17fb46e0674c0ab6b

(Pay close attention to the Z axis)
(Mainly happens when mouse move in up)

local Plr = game.Players.LocalPlayer
local Chr = Plr.Character or Plr.CharacterAdded:Wait()
local Cam = game.Workspace.CurrentCamera
local RunService = game:GetService("RunService")
local Mouse = Plr:GetMouse()

local Launcher = game.Workspace.MissileLauncher.Launcher
local LauncherCFrame = Launcher:GetPrimaryPartCFrame()
local YCFValue = Launcher.CFValue
YCFValue.Value = LauncherCFrame

local Base = game.Workspace.MissileLauncher.Base
local BaseCFrame = Base:GetPrimaryPartCFrame()
local XCFValue = Base.CFValue
XCFValue.Value = BaseCFrame

local TweenService = game:GetService("TweenService")

--Tweens the CFrame Value
function updateYTween(CF)
	local tweenInfo = TweenInfo.new(0.7)
	local CFTween = TweenService:Create(YCFValue, tweenInfo, {Value = CF})
	
	CFTween:Play()
end

function updateXTween(CF)
	local tweenInfo = TweenInfo.new(0.7)
	local CFTween = TweenService:Create(XCFValue, tweenInfo, {Value = CF})

	CFTween:Play()
end

RunService.RenderStepped:Connect(function()	
	--// X
	local XRotation = CFrame.Angles(0, math.rad(Mouse.Hit.LookVector.X * -100), 0) --Turns LookVector X into angles
	local XCF = BaseCFrame * XRotation --Turns the calculated angle into CFrame for the model
	local CalculateX = (XCF:ToOrientation()*100) --Gets the orientation of the CFrame and makes it larger
	
	updateXTween(XCF)
	
	--Sets base model primary part cframe to the cframe value
	Base:SetPrimaryPartCFrame(XCFValue.Value) 
	
	--XYZ Angles of CFrame Value
	local x, y, z = XCFValue.Value:ToEulerAnglesXYZ()
	
	--// Y
	local YRotation = CFrame.Angles(math.rad(Mouse.Hit.LookVector.Y * 100), 0, 0)  --Turns LookVector Y into angles
	local YCF = LauncherCFrame * YRotation --Turns the calculated angle into CFrame for the model
	local CalculateY = (YCF:ToOrientation()*100) --Gets the orientation of the CFrame and makes it larger


	if CalculateY < 55 and CalculateY > -35 then
		updateYTween(YCF)
	end
	
	--Sets laucher model primary part cframe to the cframe value
	--Mutiply it by the base rotation so that the launcher follows the base
	Launcher:SetPrimaryPartCFrame(YCFValue.Value * CFrame.Angles(0, -y, 0))
end)

Why this happens is fairly obvious, you may not have included a Z in your calculations, but if the user moves their mouse, it does have a Z, which you ignore, you’ll have to try shoot at the ground at the given mouse location, or calculate how far you need to shoot for it to hit higher, where the user has their mouse.

I only used Mouse.Hit.LookVector.Y and Mouse.Hit.LookVector.X. I have not used the Z.

I am not completely sure if this is the issue but it may be due to gimbal locking

As @Thedagz said, this could be due to multiple changes to a single object’s orientation (CFrame angles) - about this in specific, you can read more here.

To solve this, I’d recommend to try and make sure that the previous tween is finished before you start the next one; Simply wait with making a new change until the previous movement is finished.

You could instead of making it take a specific time, always make it only move towards the mouse a specific smaller increment on every RenderStepped event.

I just tried without the tween and like you said increasing the stud ever render. I got the same result as before. I really don’t think is the tween but perhaps the angles and CFrame itself.

1 Like

In that case, you could try modifying the Z orientation of the CFrame to 0 of the base/turret the line after you modify the rest of the CFrame.

How would I modify it to zero?

Either multiply with CFrame.new(0,0,0,0,0,1) or CFrame.Angles(0,0,1) (or just set the orientation Z rotation property to 0

1 Like

Hey, sorry for the super late reply. Turns out it is gimble locking. How can I resolve this?

Not too experience in the topic but I typically use CFrame.fromAxisAngle to do rotations in more than 1 axis