Reading voxels on the client

Hello, so I made a local script placed in the StarterCharacterScripts folder (loaded in the character). For some reasons, there is no problems reading the region where my camera lies and during every runtime the camera’s region voxels are successfully read and the according effects apply. Now, during most runtimes, the game struggles to read the voxel’s at the player’s head position region. It rarely works and returns the 3D table with the right materials but most of the time it only returns the array filled with Enum.Material.Air even if the player region is currently underwater. I should mention that my character always spawns in a region of Enum.Material.Air. I did a series of tests, including expanding the voxel’s region resolution, printing the output of the reading on the client and it still doesn’t work most of the time. Since this problem happens unpredictably depending on the runtime, I assume it has to do something with the fact that it’s a local script but nothing more. At first there were errors thrown in the output about materials[1][1][1] being nil and by the nature of the function ReadVoxels() streaming the data in the array I assume it didn’t have time to load correctly before the script would try to get the data the first times but I’m still a bit confused and it’s been month I tried to figure out why it does that. Also note that before when I first created this script, it would always work perfectly during EVERY runtime and I though maybe Roblox updated their engine so something might have changed.

local character = script.Parent
local terrain = workspace:WaitForChild("Terrain")
local head = character:WaitForChild("Head")

-- Splash
character:WaitForChild("Humanoid").StateChanged:Connect(function(oldState, newState)
	if oldState == Enum.HumanoidStateType.Freefall and newState == Enum.HumanoidStateType.Swimming or oldState == Enum.HumanoidStateType.Running and newState == Enum.HumanoidStateType.Swimming then
		game.ReplicatedStorage.Remote.AddSplash:FireServer(character.HumanoidRootPart.Position + Vector3.new(0, 1, 0))
	end
end)

local underwaterSound = game.SoundService.UnderwaterSound
local tweenService = game:GetService("TweenService")
local underWaterSoundTweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut, 0, false)

local underwaterSoundFadeIn = tweenService:Create(underwaterSound, underWaterSoundTweenInfo, {Volume = 0.5})
local underwaterSoundFadeOut = tweenService:Create(underwaterSound, underWaterSoundTweenInfo, {Volume = 0})

underwaterSoundFadeOut:Play()

local states = {
	isUnderwater = false
}

function checkMaterialAtVector(position)
	local expansion = 2
	local region = Region3.new(
		position - Vector3.new(expansion, expansion, expansion), 
		position + Vector3.new(expansion, expansion, expansion)
	):ExpandToGrid(4)
	
	local voxels = terrain:ReadVoxels(region, 4)
	
	return voxels[1][1][1]
end

function checkPlayer()
	local isUnderwater = not (checkMaterialAtVector(head.Position + Vector3.new(0, 2, 0)) == Enum.Material.Air)
	
	if states.isUnderwater ~= isUnderwater then
		states.isUnderwater = isUnderwater
		
		if states.isUnderwater then
			underwaterSoundFadeIn:Play()
		else
			underwaterSoundFadeOut:Play()
		end
	end
	
	if states.isUnderwater ~= character.Data.IsUnderwater.Value then
		game.ReplicatedStorage.Remote.ToggleIsUnderwater:FireServer(isUnderwater)
	end
end

function checkCamera()
	local isInWater = checkMaterialAtVector(workspace.CurrentCamera.CFrame.Position + Vector3.new(0, 2, 0)) == Enum.Material.Water

	if isInWater then
		game.Lighting.Blur.Enabled = true
	else
		game.Lighting.Blur.Enabled = false
	end
end

while task.wait() do
	checkPlayer()
	checkCamera()
end

PS: You can remove the splash function and logic and the remote event calls if you want to test on your side (Remotes used for a doublecheck of player’s position on the server to avoid fake data being sent, even if the client still has the control of the player’s position)

Problem was solved. It was actually because of how I would only get the player’s character head only once.

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