Pokemon Type Camera

I want to create a camera where I can control the pivot point and smoothly orbit the camera in a direction when a player reaches a part of the map like kinda like Pokemon.

I am new to scripting and what I have so far is probably unpractical so any help would help! I have tried ROBLOX Documentation as well not much help as I learn better from videos.

local RunService = game:GetService("RunService")
local Players = game:GetService("Players")

local OFFSET = Vector3.new(20, 20, 20)

Part1 = workspace:WaitForChild("Part1")

local region1 = true

local player = Players.LocalPlayer

local camera = workspace.CurrentCamera

player.CameraMinZoomDistance = 10

camera.FieldOfView= 45


-- Detatch the character's rotation from the camera
UserSettings().GameSettings.RotationType = Enum.RotationType.MovementRelative

local function onRenderStep()
	local character = player.Character
	if character then
		local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
		if humanoidRootPart then
			-- Update the position of the camera

			
			if region1 then
				local playerPosition = humanoidRootPart.Position
				local cameraPosition = playerPosition + OFFSET
				camera.Focus = humanoidRootPart.CFrame
				camera.CFrame = CFrame.new(cameraPosition, playerPosition) * CFrame.Angles(0, 0, 0)
				Part1.Touched:Connect(function()
					region1 = false
				end)
			end
end
			
		if region1 == false then
			local playerPosition = humanoidRootPart.Position
			local OFFSET = Vector3.new (0, 20, 20)
			local playerPosition = humanoidRootPart.Position
			local cameraPosition = playerPosition + OFFSET
			camera.CFrame = CFrame.new(cameraPosition, playerPosition) * CFrame.Angles(0, 0, 0)
			end
		
		
			-- Update the focus of the camera to follow the character
			
	
		end
	end
RunService:BindToRenderStep("Camera", Enum.RenderPriority.Camera.Value, onRenderStep)

Sorry for the very late answer, I hope this is still relevant. From my interpretation, you want something like the indoor camera seen in many Pokemon games. The way I did this uses an Object Oriented Programming approach (in Lua’s case its an advanced concept but using objects’ methods is fairly simple.) Here’s the code for the ModuleScript:

--/ Dependencies
local RunService = game:GetService("RunService")

--/ Constants
local Offset = Vector3.new(0,15,15)
local Padding = 8
local LerpConstant = 0.75

--/ Class
local FixedCam = {}
FixedCam.__index = FixedCam

function FixedCam.New(player : Player, focus : BasePart, smooth : boolean)
	local self = setmetatable({}, FixedCam)
	
	self.hrp = player.Character.HumanoidRootPart or player.CharacterAdded:Wait():WaitForChild("HumanoidRootPart")
	self.focus = focus
	self.smooth = smooth or false
	self.camera = workspace.CurrentCamera
	
	return self
end

function FixedCam:Start()
	repeat task.wait() until self.hrp ~= nil
	self.camera.CameraType = Enum.CameraType.Scriptable
	RunService:BindToRenderStep(self.focus.Name.."_FixedCamera", Enum.RenderPriority.Camera.Value, function()
		local min_x, max_x = self.focus.Position.X-((self.focus.Size.X/2)-Padding), self.focus.Position.X+((self.focus.Size.X/2)-Padding)
		local temp_cf = CFrame.new(self.hrp.CFrame.Position+Offset)  
		local final_cf = CFrame.new(math.clamp(temp_cf.X, min_x, max_x),temp_cf.Y, temp_cf.Z) * CFrame.Angles(-math.atan2(Offset.Y, Offset.Z),0,0)
		if self.smooth == true then
			self.camera.CFrame = self.camera.CFrame:Lerp(final_cf, LerpConstant)
		else
			self.camera.CFrame = final_cf
		end
	end)
end

function FixedCam:Stop()
	RunService:UnbindFromRenderStep(self.focus.Name.."_FixedCamera")
	self.camera.CameraType = Enum.CameraType.Custom
end

return FixedCam

The only things you need to change here are the Offset, Padding, and LerpConstant values. The first is self explanatory, and the use of the other two are as follows:

Padding: The number value in studs away from the edge of the floor where the camera will stop moving. Must be a number in the range of 0 to half of the X size of the floor (otherwise everything will break)

LerpConstant: The number value that represents how smooth the camera is. This only matters if you enable smoothness when constructing the camera (which I will get into later.) It’s an alpha value, so it is a decimal number from 0 to 1. 0 makes the camera move freakishly slow, and 1 makes the camera move instantly. I find 0.75 to be a nice value.

Now, lets get into making it all work. In a LocalScript, write the following code:

local LocalPlayer = game:GetService("Players").LocalPlayer
local FixedCamera = require() -- put the path to FixedCamera ModuleScript inside the parenthesis

local CameraFocus = workspace.Floor -- replace with the path to your preferred floor
local smooth = true -- true or false depending on preference, false is instant

local camera = FixedCamera.New(LocalPlayer, CameraFocus, smooth)

camera:Start()

task.wait(4)

camera:Stop()

Now we have an easy to use fixed camera system! You can do a lot with this; games like Loomian Legacy use this kind of system for their indoor camera, and it has more use cases beyond this. This is a very basic implementation, and I’m sure the computations I did can be optimized more. Hopefully this helps you get started!