How to limit a camera's zoom in and out range using the distance between parts and/or camera position

I’m currently trying to make a camera system that’s extremely similar to smash bros ultimate. I’m somewhat new to scripting but I pick up on things fast if explained well.

I like how the camera system moves up until both parts are extremely close or super far away from each other. My goal is to limit the zoom in when both parts are at a specific position. For an example, if 2 parts are 20 studs away from each other, I want the camera to smoothly stop zooming in and hold position until the parts are further away again. https://gyazo.com/54947de532f65022cbd1e45a18567511

Also I’m trying to make it to where if the parts are at a specific position the camera doesn’t track the parts so that they can’t be seen in the camera (this is so that I can experiment with viewport frames) and create a type of death box.
https://gyazo.com/cc96f9f80249564de26dcd197c78a6ba

I tried while loops and if statements within the renderstepped function to change the script zoffset when the distance between the parts are < 16. However it doesn’t work and it bugs out. I’m assuming it has something to do with the renderstep but I’m not exactly sure.

Here’s the code (I placed it in the startergui)

--Services
local rs = game:GetService("RunService")
--Camera
local cam = workspace.CurrentCamera
--CameraOffsets
local xoffset = 0
local yoffset = 2
local zoffset = 5
--Tracking
local tracking = workspace.Tracking
local Player1 = workspace.Tracking.Player1
local Player2 = workspace.Tracking.Player2
--Camera Creation
local camPart = Instance.new("Part")
camPart.Anchored = true
camPart.Name = "CamPart"
camPart.Parent = workspace
camPart.Transparency = 1
camPart.CanCollide = false
--Average position between parts
function calculateAveragePosition()
	local total = Vector3.new()
	for _, humrootpart in pairs(tracking:GetChildren()) do    
		total += humrootpart.Position
	end
	return total / #tracking:GetChildren()
end
--Average Magnitude between parts
function calculateAverageMagnitude()
	local total = 0
	for _, humrootpart in pairs(tracking:GetChildren()) do    
		total += (humrootpart.Position - camPart.Position).Magnitude
	end

	return total / #tracking:GetChildren()
end
--CameraType Change
rs.RenderStepped:Connect(function()
	local averagePos = calculateAveragePosition()
	local averageMagnitude = calculateAverageMagnitude() + zoffset
	
	rs.Heartbeat:Wait()
	cam.CameraType = Enum.CameraType.Scriptable

	camPart.Position = averagePos
	cam.CFrame = camPart.CFrame * CFrame.new(Vector3.new(xoffset, yoffset, averageMagnitude))
end)

rs.RenderStepped:Connect(function()
	rs.Heartbeat:Wait()
	print("Player1 and Player2 are " .. math.floor((Player1.Position - Player2.Position).Magnitude) .. " studs away")
end)

I’m not asking for anyone to make the script for me, just asking for tips on how to improve it (if you do improve on the script I appreciate it!).

How i would approach this is by setting the camera position in the middle of both players and off by an offset. I would do (plr1.position + plr2.position)/2, and then set the offset away from the arena to be a coefficient * the distance between the 2 players.

2 Likes

This will help you, try this at a local script

workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable

local Player1,Player2 = Instance.new("Part",workspace),Instance.new("Part",workspace)

Player1.Anchored = true

Player2.Anchored = true

Player1.CanCollide = false

Player2.CanCollide = false

Player1.Position = Vector3.new(0,10,0)

Player2.Position = Vector3.new(0,10,10)

task.spawn(function()

while game:GetService("RunService").RenderStepped:Wait() do

Player1.Position += Vector3.new(0,0,math.cos(os.clock())/10)

Player2.Position -= Vector3.new(0,math.cos(os.clock())/10,0)

end

end)

game:GetService("RunService").RenderStepped:Connect(function()

local Distance = Player1.Position-Player2.Position

local origin = Player1.Position

local pos = Distance.Unit*Distance.Magnitude/2

workspace.CurrentCamera.CFrame = CFrame.new(origin-pos+Vector3.new(Distance.Magnitude,0,0),origin-pos)

end)
1 Like

Oh I didn’t see this “I’m not asking for anyone to make the script for me, just asking for tips on how to improve it (if you do improve on the script I appreciate it!).” sorry

1 Like

No it’s completely fine lol, as long as the scripts help me figure out things I don’t mind.

Okay so I think I somewhat figured out the zooming in part of the script (although as you can see it glitches before it tracks when the players are close to each other, I want it to transition into it smoothly). I’m guessing TweenService could maybe fix that? However I’m still not sure how to make the camera stop moving when the parts are at a certain position.

Possible oof on my part but it could also be the fact that instead of using actual players I’m using parts while using studio move feature.

To make it smooth, I like to use CFrame:Lerp. I would do

Workspace.Camera.CFrame = Workspace.Camera.CFrame:Lerp(NewCFrame, .5?)

I’m not sure why there is a section where the camera freezes. To limit the amount that the camera can zoom, I would do Math.Clamp() on the offset.

1 Like