This is very hard to explain, so I will use pictures.
In this picture here, the ground that is selected is rotated -150° on the y-axis.
(Don't mind the red bricks. I will manage them later.)
I am trying to make an angled overhead camera, so that when playing, the ground in the camera's view seems to be straight, meaning it is not rotated. Only the ground, not the rest of the place. Note: I only want to rotate the camera, not the ground.
If you don't understand, here is (close to) what I mean by saying "straight." The ground I am focusing on does not seem to be rotated on the y-axis in the image.
Here is the code I have now. The overhead camera mode in the script is toggled using a remote event. If the event is fired and the parameter overheadModeOn is passed as true, then the camera do calculations based on the ground that is passed in the parameter area.
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remotesAndBinds = ReplicatedStorage:WaitForChild("RemotesAndBinds")
local toggleOverheadCameraMode = remotesAndBinds:WaitForChild("ToggleOverheadCameraMode")
local OFFSET = Vector3.new(0,40,40)
local TOP_DOWN_FOV = 30
local NORMAL_FOV = 50
local LIMIT_FACTOR = 0.75
local LIMIT_Z_OFFSET = Vector2.new(OFFSET.Z*1.5, OFFSET.Z*0.75)
local ANGLE_OFFSET = 45 -- CFrame.fromAxisAngle(Vector3.new(-1,0,0), math.rad(45))
local player = Players.LocalPlayer
local camera = game.Workspace.CurrentCamera
local currentArea = nil
local bounds
local primaryPartCFrame
local overheadMode = false
toggleOverheadCameraMode.OnClientEvent:Connect(function(overheadModeOn, area)
overheadMode = overheadModeOn
if overheadMode then
currentArea = area
bounds = currentArea:GetExtentsSize()
primaryPartCFrame = currentArea:GetPrimaryPartCFrame()
end
end)
local function onRenderStep()
local character = player.Character
if character and overheadMode and currentArea then
camera.CameraType = Enum.CameraType.Scriptable
camera.FieldOfView = TOP_DOWN_FOV
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
if humanoidRootPart then
local playerPosition = humanoidRootPart.Position
local originalCameraPosition = playerPosition + OFFSET
local xMin = primaryPartCFrame.X + ((-bounds.X * LIMIT_FACTOR - OFFSET.X / 2) / 2)
local xMax = primaryPartCFrame.X + ((bounds.X * LIMIT_FACTOR + OFFSET.X / 2) / 2)
local zMin = primaryPartCFrame.Z + (LIMIT_Z_OFFSET.X + LIMIT_FACTOR * (-bounds.Z - OFFSET.Z) / 2)
local zMax = primaryPartCFrame.Z + (LIMIT_Z_OFFSET.Y + LIMIT_FACTOR * (bounds.Z + OFFSET.Z) / 2)
local x = math.clamp(originalCameraPosition.X, xMin, xMax) -- originalCameraPosition.X
local y = originalCameraPosition.Y
local z = math.clamp(originalCameraPosition.Z, zMin, zMax) -- originalCameraPosition.Z
-- print(z)
local cameraPosition = Vector3.new(x,y,z)
camera.CFrame = CFrame.new(cameraPosition) * CFrame.fromAxisAngle(Vector3.new(-1,0,0), math.rad(ANGLE_OFFSET))
-- print(camera.CFrame)
end
else
camera.CameraType = Enum.CameraType.Custom
camera.FieldOfView = NORMAL_FOV
end
end
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, onRenderStep)
The result when triggering the event is just this. However, I want the camera to rotate so that its view shows the ground to be straight, not at an angle.
Also, here is my setup in the Explorer. The code I presented is a "child" of StarterPlayerScripts.
If you have any questions, please leave them in the comments. Thanks.
