Camera Tilting When Character Is Tilted On A Surface

Hi there!

I’m currently making a sonic game, I have the whole engine ready but there is one problem

I would like to add camera surface tilting but I really don’t know how to do it, this is what id like to achieve

but this is what i have so far

i would want to still be able to move my camera when tilted, its kinda like those gravity/wall script if you walk on a wall, your camera will re-adjust to the tilt, but for this i would like it so it would be able to make 360 degree turns, but i dont know how to do that because of roblox’s camera rotation limitations

anyways thank you for your time!

2 Likes

I don’t know how to exactly provide an exact answer, but you could probably do another fork of the PlayerModule fork by EgoMoose in his WallStick and Gravity Controllers WallStick/Gravity Controller

1 Like

Another thing would be getting the normal value from the surface the player is currently standing on, this could be done with raycasting about every frame to every other frame. You could then just set the camera up direction based off of this normal since it’s what’s already included in the fork. I’ve done about a medium level dive through what is capable in it so I probably wouldn’t be able to answer much.

[EDIT] Also by the looks of your movement system this wouldn’t be that hard to pull off either with raycasting

1 Like

This is pretty close to what you want. That Sonic camera is pretty sophisticated so it’s not a 100% match

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params:AddToFilter(char)

local ray_direction = Vector3.yAxis * -5
local offset = 25
local rotating = false
local lastdir = nil
local dur = 0
local lerplook = nil

UIS.InputEnded:Connect(function(input, proc)
	if input.UserInputType.Value == Enum.UserInputType.MouseButton2.Value then
		rotating = true
		dur = 0
	end
end)
RunS.Heartbeat:Connect(function(step)
	local nextpos = char.PrimaryPart:GetPivot().Position
	local rc_result = workspace:Raycast(nextpos, ray_direction + char.PrimaryPart.CFrame.LookVector * 2, params)
	if rc_result == nil then
		lastdir = camera.CFrame.LookVector
		return
	end
	local zdir = rc_result.Normal:Cross(char.PrimaryPart.CFrame.RightVector)
	local zframe = CFrame.new(Vector3.zero, zdir)

	
	if UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton2) then
		lastdir = camera.CFrame.LookVector
	else
		if rotating then
			if lerplook == nil then
				lerplook = lastdir
			end
			if dur >= 1 then
				lerplook = nil
				dur = 0
				rotating = false
			else
				lerplook = lastdir:Lerp(zdir, dur)
				camera.CFrame = CFrame.lookAlong(camera.CFrame.Position, lerplook)
				dur += (step*2)

				
			end
		elseif not rotating then
			if zdir:Angle(camera.CFrame.LookVector) > 0.1 then
				lastdir = camera.CFrame.LookVector
				rotating = true
				dur = 0
				
			else
				camera.CFrame = CFrame.lookAlong(nextpos + -offset*(char.PrimaryPart.CFrame.LookVector), zdir)
			end
		end
	end
end)