Weird CFrame behavior

So I am trying to have a part X be behind part Y, while looking at a point in front of part Y.

However, some weird stuff starts happening at certain orientations:

Can someone explain what is happening so I could compensate for this unwanted rotation? I am not too familiar with CFrames, so this has me stumped.

Here is the script if that helps, though I’m not exactly asking for the answer, I just want to be guided in the right direction.

local Camera = workspace.CamSim
local From = workspace:WaitForChild("Start")

while true do
	Camera.CFrame = From.CFrame * CFrame.new(Vector3.new(0,10,25))

	local RotX,_,RotZ = Camera.CFrame:ToEulerAnglesXYZ()

	local LookAt = From.CFrame * CFrame.new(0,0,-50)

	RotX = math.deg(RotX)
	
	if RotX < 90 and RotX > -90 then --to keep the top facing up
		Camera.CFrame = CFrame.new(Camera.CFrame.Position,LookAt.Position)*CFrame.Angles(math.rad(0),math.rad(0),RotZ)
	else
		Camera.CFrame = CFrame.new(Camera.CFrame.Position,LookAt.Position)*CFrame.Angles(math.rad(180),math.rad(180),RotZ)
	end
	task.wait()
end

Try just multiplying one CFrame by some offset like this:

local y = workspace.y

local x = script.Parent
while true do
	y.CFrame = x.CFrame * CFrame.new(0,4,8)
	task.wait()
end

1 Like

Doesn’t doesn’t quite achieve the effect I wanted, but thanks for trying to help anyway!

I ended up doing a bit of math instead by finding the angle between the Camera position and the place to look at, then turning the Camera’s CFrame by that.

This might seem weird since I could have done CFrame.new(cam,lookat), but that align the camera to the ground rather than keep its current orientation.

1 Like

Your code looks very complicated for what it does, here is a simplified version:

local Camera = workspace.CamSim
-- Reminder: you will only need a :WaitForChild for objects that are created
-- "dynamically", AKA through a script and are not placed within the
-- Studio Explorer before the game is run
local From = workspace:WaitForChild("Start")

while true do
    Camera.CFrame = From.CFrame * CFrame.new(0, 10, 25)

    local LookAtPosition = (From.CFrame* CFrame.new(0, 0, -50)).Position
    Camera.CFrame = CFrame.lookAt(Camera.CFrame.Position, LookAtPosition)
    
    task.wait()
end

I have a few things to comment on though:

Calling CFrame.new with a second argument has been superseded (i.e. replaced) by it’s own unique function CFrame.lookAt. You should use that instead:

(Yes, I know the video quality sucks, I set to export at 480p after trimming it and didn’t realize that was this bad)
(Tip: You can right-click an object and click “Show orientation indicator” to bring up that little circle and green arrow that indicate the front and top face of an object respectively. Yeah, I know it doesn’t really demonstrate how you don’t need to have extra code to ensure the object’s top face is always facing up, but just trust me bro when I say that no matter what I did, the object’s top face never faced the incorrect direction when I was doing some extra testing.)

Thank you for your input, however the result is not quite what I wanted as the horizontal rotation is not preserved when using lookAt (or the old method)

The WaitForChild is just a remnant from when it was a localscript

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.