Changing camera CFrame onTouch of a trigger

Hello,
I am trying to make a Silent Hill/ Resident Evil type horror game, but I’m noobish at scripting. So basically what I’m trying to achieve is changing the CFrame of a players camera when a player enters a trigger part. The camera must always rotate with (be facing) the players position. There is loads of camera manipulation tutorials, but I can’t find any that explain how to do this. This is what I have so far, it doesn’t work. I have the “CameraChangeEvent” RemoteEvent in ReplicatedStorage.
Trigger Script (parented to the trigger part):

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")

local triggerPart = script.Parent 

triggerPart.Touched:Connect(function(otherPart)
	local character = otherPart.Parent
	local humanoid = character:FindFirstChild("Humanoid")
	local player = game.Players:GetPlayerFromCharacter(character)

	if humanoid and player then
		remoteEvent:FireClient(player)
	end
end)

LocalScript in StarterPlayerScripts:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local cameraChangeEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")

cameraChangeEvent.OnClientEvent:Connect(function()
	local player = game.Players.LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

	local newCameraCFrame = CFrame.new(Vector3.new(-39.2, 12.8, -76.3))

	-- Make the camera look at the player
	newCameraCFrame = newCameraCFrame * CFrame.new(0, 0, -10) -- Adjust the offset as needed
	newCameraCFrame = newCameraCFrame:pointToWorldSpace(humanoidRootPart.Position)

	game.Workspace.CurrentCamera.CFrame = newCameraCFrame
end)

Any help or info, or where I can research up to date documentation will be of great help. Thanks very much in advance.

2 Likes

Do you get any errors? I may be able to help if I know what exactly is not working.

2 Likes

Actually yes, Line 15 in the local script, “Unable to assign property CFrame. CoordinateFrame expected, got Vector3”:

game.Workspace.CurrentCamera.CFrame = newCameraCFrame
2 Likes

Get the CFrame of the HumanoidRootPart, not the position

3 Likes

Make that Vector3 a CFrame.

Code:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local cameraChangeEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")

cameraChangeEvent.OnClientEvent:Connect(function()
	local player = Players.LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

	-- Make the camera look at the player
	local newCameraCFrame = CFrame.new(-39.2, 12.8, -76.3)
	newCameraCFrame *= CFrame.new(0, 0, -10) -- Adjust the offset as needed
	newCameraCFrame = newCameraCFrame:PointToWorldSpace(humanoidRootPart.Position)

	workspace.CurrentCamera.CFrame = CFrame.new(newCameraCFrame)
end)
3 Likes

I tried this, but it just makes the camera twitch when walking into the trigger. The way I have it now makes it twitch, but it the camera almost moves to the correct position I want it. Only issue is the camera is still fixed (following) the player. I need it to stay at this CFrame until the player has entered a different trigger. This is what I’m using now:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local cameraChangeEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")

cameraChangeEvent.OnClientEvent:Connect(function()
	local player = game.Players.LocalPlayer
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

	local newCameraPosition = Vector3.new(-39.2, 12.8, -76.3)

	-- Make the camera look at the player
	local offset = Vector3.new(0, 0, -10) -- Adjust the offset as needed
	local lookAtPosition = humanoidRootPart.Position
	local newCameraCFrame = CFrame.new(newCameraPosition, lookAtPosition + offset)

	game.Workspace.CurrentCamera.CFrame = newCameraCFrame
end)

2 Likes

Set the CameraType to Scriptable to achieve this. Set it back to Custom and it will automatically focus back on the player.

Code:

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

local player = Players.LocalPlayer
local cameraChangeEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")
local CurrentCamera = workspace.CurrentCamera

cameraChangeEvent.OnClientEvent:Connect(function()
	local character = player.Character or player.CharacterAdded:Wait()
	local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

	local newCameraPosition = Vector3.new(-39.2, 12.8, -76.3)

	-- Make the camera look at the player
	local offset = humanoidRootPart.CFrame.LookVector * -10 -- Adjust the offset as needed
	local lookAtPosition = humanoidRootPart.Position
	local newCameraCFrame = CFrame.lookAt(newCameraPosition, lookAtPosition + offset)
	
	CurrentCamera.CameraType = Enum.CameraType.Scriptable
	CurrentCamera.CFrame = newCameraCFrame
end)

I also fixed your offset code to work if the player faced any direction when this code is run.

You should also put some variables outside the function if possible in order for the script to be more readable and for the functions to take less time indexing. I have done this for you though.

3 Likes

Thank you so much! This works perfectly. It’s exactly the effect I was looking for!

2 Likes

No problem. If you have any other concerns, feel free to ask for help.

I would love to see an end result too if that’s possible. Camera animations are nice to look at.

2 Likes

Also, one more optimization for your Trigger script. You don’t need to check for a Humanoid, because you don’t need it in your :FireClient event, and a Humanoid isn’t needed in any of the scripts.

Code:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:WaitForChild("CameraChangeEvent")

local triggerPart = script.Parent 

triggerPart.Touched:Connect(function(otherPart)
	local player = Players:GetPlayerFromCharacter(otherPart.Parent)

	if player then
		remoteEvent:FireClient(player)
	end
end)
1 Like

All this has put me on the right track.Thanks again! :sunglasses:

3 Likes

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