Hi,
Ive been making a snowy island and I wanted to detect if the player is in the water and then the start to lose health because the water is really cold. The issue is that I cant seem to access the Humanoid Root Part. Ive tried a WaitForChild:() but then I get and Infinite yield. This is a local script in starter player scripts and Im accessing the player using Players.LocalPlayer.
Code
local Player = game.Players.LocalPlayer
local root = Player.Character.HumanoidRootPart
local min = root.Position - (4 * root.Size)
local max = root.Position + (4 * root.Size)
local region = Region3.new(min,max):ExpandToGrid(4)
local material = workspace.Terrain:ReadVoxels(region,4)[1][1][1]
if material == Enum.Material.Water then
print("under water")
end
local LocalPlayer = game:GetService("Players").LocalPlayer
function Update(dt)
local Character = LocalPlayer.Character
if not (Character) then
return
end
local HumanoidRootPart = Character:FindFirstChild("HumanoidRootPart")
if not (HumanoidRootPart) then
return
end
local min = HumanoidRootPart.Position - (4 * HumanoidRootPart.Size)
local max = HumanoidRootPart.Position + (4 * HumanoidRootPart.Size)
local region = Region3.new(min,max):ExpandToGrid(4)
local material = workspace.Terrain:ReadVoxels(region,4)[1][1][1]
if material == Enum.Material.Water then
print("under water")
end
end
game:GetService("RunService").Heartbeat:Connect(Update)
The way I see it is that you are trying to read the terrain voxels. My way might be the best way for you to get the HumanoidRootPart and do your reading voxel thing.
If this helps you, please accept it as a solution. Thanks.
p.s: you can bind it to whatever you like; Stepped, Renderstepped. This is just an example.
You could try this. The character is probably not loaded in yet, so we can use Player.CharacterAdded:Wait() to wait until it is loaded in.
local Player = game.Players.LocalPlayer
local character = Player.Character or Player.CharacterAdded:Wait()
local root = character:WaitForChild("HumanoidRootPart")
The reason it’s required is because the Character is somewhat separate from the player.
I’m going to give you a scenario to describe what happens
-- Player Joins the game
local Player = game.Players.LocalPlayer -- Defines the player
local Character = Player.Character-- Attempts to grab the players character
-- Game loads in the character
As you can see you’re attempting to refrence the Character before It’s been loaded in.
Throwing a :CharacterAdded:Wait() will fix this problem.
Another scenario of a potential problem.
-- Player Joins the game
local Player = game.Players.LocalPlayer -- Defines the player
Player.CharacterAdded:Wait()
local Character = Player.Character-- Grabs the current player model of the player
local HumanoidRootPart = Character.HumanoidRootPart
-- Player Dies and is given a new Character
Character.HumanoidRootPart.Transparency = 1 -- The Character that "Character" is referencing has been destroyed, and you'll need to get a new one.
The easy fix to this entire problem is just to throw it into a starterCharacterScript instead.
Local Scripts inside StarterCharacterScripts will load after the characters were added. This will fix the problem of the character dying, due to a new script being created on respawn. And you could easily reference the character with
script.Parent
Script location
After clicking play
I hope this helps, let me know if you have any questions.
Edit: Another easy fix would be to wrap your script around a CharacterAdded event.
local Player = game.Players.LocalPlayer
Player.CharacterAdded:Connect(function(Character)
print(Character:WaitForChild("HumanoidRootPart").Name) -- HumanoidRootPart
end)
Ah upon reflection it looks like @imtkl’s solution would be efficient. I didn’t take into account you’re not only trying to define HRP, but also detecting when they’ve gone underwater. I apologize