How to keep camera's relative orientation?

I have this plateform which spins around a center point and right now the player moves with it, however, their camera not so much:

Any solutions to how I would fix this?

2 Likes

You could try changing the cameraType to Follow or Fixed

I tried that, but then I can’t move my camera

Here’s what you can do, measure the rotational change of the HumanoidRootPart on a per-frame basis and apply that delta to the camera’s CFrame

The following script is an EXTREMELY HACKY workaround that I can think of at the top of my head; you should find a better way to do this. If you do plan on using this, you need to figure out a way to disable it when the player is moving and only enable it when the player isn’t controlling their avatar

local lp = game:GetService('Players').LocalPlayer
local rus = game:GetService('RunService')

local hrp: BasePart = (lp.Character or lp.CharacterAdded:Wait()):WaitForChild('HumanoidRootPart')
lp.CharacterAdded:Connect(function(ch)
	hrp = ch:WaitForChild('HumanoidRootPart')
end)

local prev: CFrame = CFrame.identity
rus:BindToRenderStep('RotateWithHRP', Enum.RenderPriority.Camera.Value+1, function()
	local current: CFrame = hrp.CFrame.Rotation
	local cam: Camera = workspace.CurrentCamera
	local camCF: CFrame = cam.CFrame
	local focus: CFrame = cam.Focus
	cam.CFrame = focus*camCF.Rotation * (prev:Inverse() * current) * CFrame.new(0, 0, (camCF.Position-focus.Position).Magnitude)
	prev = hrp.CFrame.Rotation
end)

3 Likes

If you think that’s hacky, I tried spinning the player’s camera with the platform, which kind of worked, just if it wasn’t timed right the platform and the player’s camera would be out of sync. So I just changed the object it’s copying the rotation from, from the HumanoidBasePart to my platform and it did work:

However, it has the same problem as my previous solution (besides the out-of-sync part)-it spins faster when looking from top down or from the bottom

Hey, I managed to fix all of your problems and also made it rotate relative to what the player is standing on. It uses a raycast to detect the “floor”. The camera-rotating-at-different-speeds was simply because the CFrames are multiplied in the wrong order lol

local lp = game:GetService('Players').LocalPlayer
local rus = game:GetService('RunService')

local char = lp.Character or lp.CharacterAdded:Wait()
local hrp: BasePart = char:WaitForChild('HumanoidRootPart')
local hum: Humanoid = char:WaitForChild('Humanoid')
local floorRCP: RaycastParams = RaycastParams.new()
floorRCP.FilterType = Enum.RaycastFilterType.Exclude
floorRCP.FilterDescendantsInstances = {char}
local floorRCdir: Vector3 = Vector3.yAxis * -4
lp.CharacterAdded:Connect(function(ch)
	char = ch
	hrp = ch:WaitForChild('HumanoidRootPart')
	hum = ch:WaitForChild('Humanoid')
	floorRCP.FilterDescendantsInstances = {ch}
end)

local prev: CFrame = CFrame.identity
local following: BasePart?
rus:BindToRenderStep('RotateWithHRP', Enum.RenderPriority.Camera.Value+1, function()
	local rcr: RaycastResult? = workspace:Raycast(hrp.Position, floorRCdir, floorRCP)
	local floor: BasePart? = if rcr and typeof(rcr.Instance) == 'Instance' and rcr.Instance:IsA('BasePart') then rcr.Instance else nil
	if floor then
		local current: CFrame = floor.CFrame.Rotation
		local cam: Camera = workspace.CurrentCamera
		local camCF: CFrame = cam.CFrame
		local focus: CFrame = cam.Focus
		
		local offset: CFrame
		if following == floor then
			offset = prev:Inverse() * current
		else
			following = floor
			offset = CFrame.identity
		end
		prev = current
		
		cam.CFrame = focus*offset*camCF.Rotation * CFrame.new(0, 0, (camCF.Position-focus.Position).Magnitude)
		return
	end
	following = nil
end)

1 Like

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