This is probably because the player’s character has not loaded in yet. Try using the CharacterAdded event, and connecting to it.
local LocalPlayer = game.Players.LocalPlayer
LocalPlayer.CharacterAdded:Connect(function(Character)
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
end)
As @OptimisticSide said you could try using CharacterAdded Event, another way to do it is doing this:
local Player = game:GetService("Players").LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
I prefer this way because it makes the code alot more cleaner, also you should use GetService instead of doing game.Service. It’s a better practice because if for some reason in universe you rename your services it will error. Good luck with your scripting!
I’d still recommend the classic Connect approach to this issue. I believe so because the character can respawn, making the previously declared HumanoidRootPart obsolete.
local Players = game:GetService("Players")
local LocalPlayer = Players.LocalPlayer
LocalPlayer.CharacterAdded:Connect(function(Character)
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
-- put the rest of your code that incorporates the local player's character here
end)
Hey, I’m sorry to say this but anti-exploits shouldn’t go on client scripts. Most exploits are done by manipulating client data, so its ultimately best to do anti-exploit checks from the server (which can’t be bypassed).
I would like to think so too, but this isn’t what actually happens. The defined HumanoidRootPart does not become obsolete at all when the player respawns. Imo, there’s no point in making a CharacterAdded event just to index something inside it when this piece of code;
works as expected, without making a full CharacterAdded event, and as @Fenix7667 mentioned, keeps your code clean.
Make sure to track the script if you’re going to parent it to the character. Deletions of instances in the character replicate for some reason and that includes server-side script instances. I don’t know if this terminates the code or not considering nothing is sent to the client in the first place but it’d be good to flag the player if the script instance is tampered with. You could avoid this overhead by not putting it in the character and therefore not in StarterCharacterScripts.
True they are never useless, but they’re also never 100% reliable. Like this function helps defend against speed exploits:
but it can only be done from client, because only the client knows its own frames per second.
But you can still prevent the same attack checking players velocities from the server.
Well as you know roblox utilizes the server-client model to support multiplayer games. The server can be known as the overseer for all clients; the server will keep track of game data and replicate them to clients. FilteringEnabled works by making the server-client communication, for the most part, one sided.
The client is the program that runs on your computer, and it needs data to know what the game looks like. The general nature of exploits will manipulate client data in some way, even code ran from the client. However, because of filteringEnabled most data from the client doesn’t get sent back to the server. So if a player deletes or creates a part client-side, then other players will not experience this alteration.
But there are cases where the server accepts signals from client (remote events), where client data replicates to server (some properties of character), and where the server depends on clients for computation (physics network ownership).
So take away the idea that a dedicated exploiter can forge or bypass client-sided defenses