Camera part instance returning as nil?

so i have this local script here. it worked just fine, until a few minutes ago when i opened the place and playtested it. all of a sudden, i’m getting an error, specifically for the blue part, ‘c_calmSeaside’. ‘Players.Ultimax_84.PlayerScripts.zoneHandler:74: attempt to index nil with ‘associatedFOV’’. i am thoroughly puzzled, because this error seems to only be thrown around half the time…

(for display, i made the camera parts visible.)

my setup:

  • there are 2 folders in the workspace: “ambienceFolder” and “cameraParts”.

  • inside of the ambience folder, there are the non-collidable parts that i create zones for.

  • in the camera parts folder, there are small invisible parts that the camera’s base CFrame is set to upon entering the zone. it looks at the HumanoidRootPart of your avatar, and uses CFrame:Lerp() as an alternative to constantly creating and destroying tweens.

  • in the camera parts themselves, there is a NumberValue, called “associatedFOV”. this is the value that the camera’s FOV tweens to, when inside of the zone.

  • inside of SoundService, there is a folder called “ambientSounds”. each of these sounds is playing, but their volume is set to 0. once a player enters a zone, it looks to see if there is a sound that shares a name with a zone. if there is, it tween’s the sound’s volume to 1, and back to 0 once the zone is exited.

  • each zone has a corresponding camera part (in the camera part folder), but has “c_” at the start of the name.

  • there are 4 zones: calmSeaside, consumerism, creepyFog, and sunset.

my script:

-- uses ZonePlus by ForeverHD

local currentCamera = workspace.CurrentCamera
local oldFOV = currentCamera.FieldOfView
local lighting = game:GetService("Lighting")
local defaultLighting = lighting.OutdoorAmbient
local tweenService = game:GetService("TweenService")
local replicatedStorage = game:GetService("ReplicatedStorage")
local zonePlus = require(replicatedStorage:WaitForChild("Zone"))
local ambienceFolder = workspace:FindFirstChild("ambienceFolder")
local localPlayer = game:GetService("Players").LocalPlayer
local cameraPartFolder = workspace:FindFirstChild("cameraParts")
local zoneController = require(replicatedStorage.Zone.ZoneController)
local soundService = game:GetService("SoundService")
local runService = game:GetService("RunService")
local lerpFactor = 0.08
local runServiceConnection

local ambientParts = {
	ambienceFolder:WaitForChild("calmSeaside"),
	ambienceFolder:WaitForChild("consumerism"),
	ambienceFolder:WaitForChild("sunset"),
	ambienceFolder:WaitForChild("creepyFog")
}

local cameraTweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out)
local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Circular, Enum.EasingDirection.InOut)
local propertyTable = {Volume = 1}
local propertyTable2 = {Volume = 0}

function captureAndResetCFrame(object: BasePart, cachedCFrame: CFrame)
	if object and cachedCFrame then
		object.CFrame = cachedCFrame
	end
end

for _, zonePart in ipairs(ambientParts) do
	local ambientZone = zonePlus.new(zonePart)
	local audioFile = soundService.ambientSounds:WaitForChild(tostring(zonePart.Name))
	local lightingGoal = {OutdoorAmbient = zonePart.Color}
	local lightingExit = {OutdoorAmbient = defaultLighting} 
	
	ambientZone:bindToGroup("ambientAreas")

	local camPart = cameraPartFolder:FindFirstChild("c_" .. tostring(zonePart.Name))
	local cachedCFrame -- store the initial cframe
	
	-- player entered and exited
	ambientZone.localPlayerEntered:Connect(function()
		local tween = tweenService:Create(audioFile, tweenInfo, propertyTable):Play()
		local lightingTween = tweenService:Create(lighting, tweenInfo, lightingGoal):Play()
		print(camPart)
		if camPart then
			local fov = tonumber(camPart.associatedFOV.Value)
			currentCamera.CameraType = Enum.CameraType.Scriptable
			cachedCFrame = camPart.CFrame -- cframe captured
			runServiceConnection = runService.RenderStepped:Connect(function()
				currentCamera.CFrame = camPart.CFrame
				local targetPart = localPlayer.Character.PrimaryPart
				local lookAtPosition = targetPart.Position
				local currentPosition = camPart.Position

				local lookAtCFrame = CFrame.new(currentPosition, lookAtPosition)
				camPart.CFrame = camPart.CFrame:Lerp(lookAtCFrame, lerpFactor)
			end)
			local fovTween = tweenService:Create(currentCamera, cameraTweenInfo, {FieldOfView = fov}):Play()
		end
	end)

	ambientZone.localPlayerExited:Connect(function()
		print(camPart)
		local lightingTween = tweenService:Create(lighting, tweenInfo, lightingExit):Play()
		local fov = tonumber(camPart.associatedFOV.Value)
		if runServiceConnection then
			runServiceConnection:Disconnect()
			-- reset the cframe
			captureAndResetCFrame(camPart, cachedCFrame)
		end
		local fovTween = tweenService:Create(currentCamera, cameraTweenInfo, {FieldOfView = oldFOV}):Play()
		currentCamera.CameraType = Enum.CameraType.Custom
		local tween = tweenService:Create(audioFile, tweenInfo, propertyTable2):Play()
	end)
end

local dictionary = {
	onlyEnterOnceExitedAll = true,
}

zoneController.setGroup("ambientAreas", dictionary)
1 Like