How would you make the camera behave like this? (Petscop-type camera)

Hello,

I’ve been thinking about how could I make a camera like this, but I cannot come up with something efficient:
https://youtu.be/teJDdkWHAdw?si=sSAOUBEq40Qql5rA&t=68 (Gameplay Starts at 1:08)

See how the camera follows the player? The player is not centered but rather is always to the side, allowing you to move around without the camera going along. I also want to achieve the transition effect it has between rooms.

How would you implement something like this? Thanks!

3 Likes

If you create an anchored part in workspace named “CameraPart” and paste the following in a localscript, which you put under StarterCharacterScripts, then you can achieve it:

local cameraPartCFrame = workspace:WaitForChild("CameraPart").CFrame
local camera = workspace.Camera

camera.CameraType = Enum.CameraType.Scriptable

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")

humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	while humanoid.MoveDirection ~= Vector3.zero do
		local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
		local newPosition = Vector3.new(
			cameraPartCFrame.X,
			cameraPartCFrame.Y,
			humanoidRootPart.Position.Z
		)
		camera.CFrame = CFrame.new(newPosition) * (cameraPartCFrame - cameraPartCFrame.Position)
		task.wait()
	end
end)

This script basically sets the position of the camera to a part and only allows it to move along the z axis. You can change which axis the camera should move along by changing the newPosition variable. This of course assumes your background, and everything is parallel to the axis you choose, but i didn’t assume that to be a problem.

(Edit: I didn’t notice you wrote about the transition effect as well. For that i guess you could just have a touch-detection part at the doors that cause the darkening of the screen, teleports the player to the new room and updates the CameraPart)

1 Like

Would just changing the position of the camera be sufficient to achieve the transition effect? (I know how to do the GUI!)

Yes i think so, but i also just realized something. In the video, there is a point where the player walks forward and the camera follows. My provided script will not do that. I’ll try to see if i can make it do so.

1 Like

Alright, I would really appreciate it. Also look into how I could make the transitions possible. Thanks!

I haven’t tried 2112Jay’s code, so it might work. However, i was invested in this problem myself, and came up with the solution:

local cameraPartCFrame = workspace:WaitForChild("CameraPart").CFrame
local camera = workspace.Camera

camera.CameraType = Enum.CameraType.Scriptable

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")

local distanceLimit = 20 --Studs between player and cam. If it exceeds this, camera will follow

local function UpdateCamera()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
	local cameraPartPosition = cameraPartCFrame.Position
	local vectorToPlr = humanoidRootPart.CFrame.Position - cameraPartPosition
	local distanceInRightVector = vectorToPlr:Dot(cameraPartCFrame.RightVector)

	local newCFrame = cameraPartCFrame + cameraPartCFrame.RightVector * distanceInRightVector

	local distance = (
		Vector2.new(newCFrame.X, newCFrame.Z) -
			Vector2.new(humanoidRootPart.Position.X, humanoidRootPart.Position.Z)
	)

	if distance.Magnitude > distanceLimit then
		local distanceXYZ = Vector3.new(distance.X, 0, distance.Y)

		local forwardAxis = Vector3.new(cameraPartCFrame.LookVector.X, 0, cameraPartCFrame.LookVector.Z).Unit

		newCFrame  = newCFrame - distanceXYZ - forwardAxis * distanceLimit
	end

	camera.CFrame = newCFrame
end

UpdateCamera() --Makes sure camera is updated before player starts walking after reset/joining

humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(function()
	local startMoveDirection = humanoid.MoveDirection
	while humanoid.MoveDirection ~= Vector3.zero and humanoid.MoveDirection == startMoveDirection do
		UpdateCamera()
		task.wait()
	end
end)

I also noticed that you could cause the loop to run more than needed with the humanoid.MoveDirection ~= Vector3.zero command, since it never stops running unless the player moves, meaning it will keep running when you walk forward and left at the same time. This code should also make sure you aren’t forced to use one axis only. Now you can rotate the CameraPart however you like, and it will follow its own kind of axis.
(Edit: Forgot to mention the most important change, it now follows your player if they move longer than 20 studs away.)

My re-wright was terrible … lol, I reposted that.

No it’s okay, i think it’s best we all try to improve the solution, so we can deliver the best possible answer.

“I think it’s best we all try to improve the solution.” This is the way …
Also the loop isn’t going to over-run, add a print after and you’ll see it only runs when moving.
I also have that directional turning option going.

My last posts were all trash …
This works, make sure you place it in StarterCharacterScripts.

-- A LocalScript in StarterPlayerScripts.StarterCharacterScripts

local camera = game.Workspace.Camera
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character:WaitForChild("Humanoid")
camera.CameraType = Enum.CameraType.Scriptable

local function updateCamera()
	while humanoid.MoveDirection ~= Vector3.new() do
		local newPosition = humanoidRootPart.Position + Vector3.new(0, 2, 10)
		camera.CFrame = CFrame.new(newPosition, humanoidRootPart.Position)
		task.wait()
	end
end

newPosition = humanoidRootPart.Position + Vector3.new(0, 2, 10)
camera.CFrame = CFrame.new(newPosition, humanoidRootPart.Position)
humanoid:GetPropertyChangedSignal("MoveDirection"):Connect(updateCamera)
updateCamera()

1 Like

Thank you, it works well. How would you resolve the issue of moving the camera?

Let’s say I want to move to another room, and change the camera’s position. What would I do? Since the camera isn’t linked to that part.

This is kind-of what I was going for, but what I meant was a static camera that moves when you go to the sides. (See how in the video, the camera is static until the Petscop guy moves past a certain threshhold to the left or right. Otherwise, it remains static.)

The script you provided me is good, but it instantly moves to the left or right. Something ideal would be like the distance thing you did when going forward, implementing it for the sides too. (If player is X studs away from the center, then follow along to the left or right.)

Ahh yeah i see. I came up with a solution, that i think works pretty reliably:
Camera System.rbxl (57.2 KB)

I uploaded a place file this time, because i made it so you can simply update the camera by this function:

local function SetCamera(player: Player, cameraCFrame: CFrame, forwardLimit: number, horizontalLimit: number)
	local cameraEvent = game.ReplicatedStorage.CameraEvent
	cameraEvent:FireClient(
		player,
		cameraCFrame,
		forwardLimit,
		horizontalLimit
	)
end

In ServerScriptService, you will find the script where this function is located. I also added parameters for the function, so you can adjust the forward and horizontal limit per camera cframe. If this isn’t quite what you were looking for or it has bugs, please let me know.

Note: To use it you will have to copy the remotevent: “CameraEvent” from ReplicatedStorage and “CameraScript” from StarterPlayerScripts into your own game at those exact locations.

Wow. This works really well and it’s exactly what I thought of. Thank you so much, you’re amazing!

If this project of mine gets released, I will be sure to credit you :)))!

1 Like

No problem, I’m happy i could help. Also, you don’t have to credit :blush:

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