Last active
February 27, 2025 22:22
-
-
Save mvyasu/9f35377e79dc2b09dfe61812ffeb5460 to your computer and use it in GitHub Desktop.
A quick and easy way to hide characters by setting attributes. If you want this to work with StreamingEnabled, you should handle the tagging of characters with a server script instead of with the provided snippet at the bottom.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --by @mvyasu | |
| --4 May 2023 | |
| --A quick and easy way to hide characters by setting attributes | |
| --To change whether characters are hidden do: game.Players:SetAttribute("HideCharacters", true) | |
| --To exclude a player's character from being hidden do: game.Players.LocalPlayer:SetAttribute("NeverHideCharacter", true) | |
| local CHARACTER_TAG = game:GetService("HttpService"):GenerateGUID() | |
| local CollectionService = game:GetService("CollectionService") | |
| local Players = game:GetService("Players") | |
| do --handles the transparency of the characters | |
| local function cleanupObject(object: any) | |
| local t = typeof(object) | |
| if t == "function" then | |
| object() | |
| elseif t == "RBXScriptConnection" then | |
| object:Disconnect() | |
| elseif t == "table" or t =="Instance" then | |
| if object.Destroy then | |
| object:Destroy() | |
| else | |
| for _,child in pairs(object) do | |
| cleanupObject(child) | |
| end | |
| table.clear(object) | |
| end | |
| elseif t == "thread" then | |
| coroutine.close(object) | |
| end | |
| end | |
| local characterCleanupObjects = {} | |
| local function onCharacterAdded(character) | |
| if characterCleanupObjects[character] then | |
| return | |
| end | |
| --the or statement is needed because apparently :GetPlayerFromCharacter() has a race condition | |
| local player = Players:GetPlayerFromCharacter(character) or Players:FindFirstChild(character.Name) | |
| if player==nil then | |
| return | |
| end | |
| local objectsToCleanup: {[any]: any} = {} | |
| characterCleanupObjects[character] = objectsToCleanup | |
| do --handles when and what to set the transparency to | |
| local wasHiddenLastUpdate = nil | |
| local function shouldBeHidden(): boolean | |
| return Players:GetAttribute("HideCharacters") and not player:GetAttribute("NeverHideCharacter") | |
| end | |
| local function setDescendantTransparency(object: any, forcedTransparency: number?) | |
| if object:IsA("BasePart") or object:IsA("Decal") then | |
| object.LocalTransparencyModifier = forcedTransparency or (if wasHiddenLastUpdate then 1 else 0) | |
| end | |
| end | |
| local function setCharacterTransparency() | |
| for _,descendant in character:GetDescendants() do | |
| setDescendantTransparency(descendant) | |
| end | |
| end | |
| local lastForceTransparencyConnection = nil | |
| local function onHiddenStatusChanged(isCharacterHidden) | |
| if player~=Players.LocalPlayer then | |
| return | |
| end | |
| if lastForceTransparencyConnection then | |
| lastForceTransparencyConnection:Disconnect() | |
| table.remove(objectsToCleanup, table.find(objectsToCleanup, lastForceTransparencyConnection)) | |
| end | |
| if isCharacterHidden then | |
| local newForceTransparencyConnection = game:GetService("RunService").RenderStepped:Connect(setCharacterTransparency) | |
| lastForceTransparencyConnection = newForceTransparencyConnection | |
| table.insert(objectsToCleanup, newForceTransparencyConnection) | |
| end | |
| end | |
| local function updateCharacterTransparency(forceUpdate: boolean?) | |
| local shouldHideCharacter = shouldBeHidden() | |
| if shouldHideCharacter==wasHiddenLastUpdate and not forceUpdate then | |
| return | |
| end | |
| if wasHiddenLastUpdate~=shouldHideCharacter then | |
| onHiddenStatusChanged(shouldHideCharacter) | |
| end | |
| wasHiddenLastUpdate = shouldHideCharacter | |
| setCharacterTransparency() | |
| end | |
| updateCharacterTransparency() | |
| table.insert(objectsToCleanup, { | |
| character.DescendantAdded:Connect(setDescendantTransparency), | |
| character.DescendantRemoving:Connect(function(descendant) | |
| setDescendantTransparency(descendant, 0) | |
| end), | |
| player:GetAttributeChangedSignal("NeverHideCharacter"):Connect(updateCharacterTransparency), | |
| Players:GetAttributeChangedSignal("HideCharacters"):Connect(updateCharacterTransparency), | |
| }) | |
| end | |
| end | |
| CollectionService:GetInstanceAddedSignal(CHARACTER_TAG):Connect(onCharacterAdded) | |
| for _,character in CollectionService:GetTagged(CHARACTER_TAG) do | |
| task.spawn(onCharacterAdded, character) | |
| end | |
| CollectionService:GetInstanceRemovedSignal(CHARACTER_TAG):Connect(function(character) | |
| local objectsToCleanup = characterCleanupObjects[character] | |
| if objectsToCleanup then | |
| cleanupObject(objectsToCleanup) | |
| characterCleanupObjects[character] = nil | |
| end | |
| end) | |
| end | |
| do --handles tagging the player with a tag defined by CHARACTER_TAG | |
| local function onCharacterAdded(character) | |
| CollectionService:AddTag(character, CHARACTER_TAG) | |
| end | |
| local function onPlayerAdded(player) | |
| player.CharacterAdded:Connect(onCharacterAdded) | |
| if player.Character then | |
| task.spawn(onCharacterAdded, player.Character) | |
| end | |
| end | |
| Players.PlayerAdded:Connect(onPlayerAdded) | |
| for _,player in Players:GetPlayers() do | |
| task.spawn(onPlayerAdded, player) | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment