i have these scripts here that toggle the visibility of models that are tagged, using CollectionService and TweenService. it works fine, except when i place the content of these scripts inside of a couple of LocalScripts and change the RunService.Heartbeat to RunService.RenderStepped, it fails to update (or even toggle) the transparencies of the children of the tagged models.
i want it to be client-sided because i do not want the script’s responsiveness to be tied to the player’s connection.
script that handles the tagging
-- handles tags & stuff
local run_service = game:GetService("RunService")
local collection_service = game:GetService("CollectionService")
local main_part = script.Parent
local decal = main_part:WaitForChild("normal")
local can_see_tx = 16569627204
local cannot_see_tx = 10198213112
local enemy_tag = "invisible_enemy"
local visibility_tag = "is_visible"
local visible_enemies = {} -- table to store visible enemies
local vision_distance = 60
local field_of_view = 90
local vision_in_front_only = true
local function target_in_vision(target, main_part)
if target and target:IsA("Model") and target.PrimaryPart then
local origin = main_part.Position
local targetPosition = target.PrimaryPart.Position
local direction = (targetPosition - origin).unit * vision_distance
local ray = Ray.new(origin, direction)
local ignore_list = {main_part}
local hit, _ = workspace:FindPartOnRayWithIgnoreList(ray, ignore_list)
if hit and target.PrimaryPart then
if hit:IsDescendantOf(target) then
if vision_in_front_only then
local unit = (targetPosition - origin).Unit
local is_looking = main_part.CFrame.LookVector
local dot = unit:Dot(is_looking)
local half_fov = math.rad(field_of_view) / 2
local max_dot = math.cos(half_fov)
if dot > max_dot then
return true
end
else
return true
end
end
end
end
return false
end
local function update_visible_enemies()
for _, enemy in ipairs(collection_service:GetTagged(enemy_tag)) do
local is_visible = target_in_vision(enemy, main_part)
local was_visible = visible_enemies[enemy]
if is_visible and not was_visible then
visible_enemies[enemy] = true
collection_service:AddTag(enemy, visibility_tag)
elseif not is_visible and was_visible then
visible_enemies[enemy] = nil
collection_service:RemoveTag(enemy, visibility_tag)
end
end
end
run_service.Heartbeat:Connect(function()
update_visible_enemies()
-- check if there are any visible enemies
if next(visible_enemies) then
decal.Texture = ("rbxassetid://" .. tostring(can_see_tx)) -- can see target
else
decal.Texture = ("rbxassetid://" .. tostring(cannot_see_tx)) -- cannot see target
end
end)
script that handles the visibility
local tween_service = game:GetService("TweenService")
local collection_service = game:GetService("CollectionService")
local enemy_tag = "invisible_enemy"
local visibility_tag = "is_visible"
local visible_enemies = {}
-- attempt #9 million, true = visible, false = invisible
local original_transparency = {}
local function set_transparency(instance, transparency)
if instance:IsA("BasePart") or instance:IsA("MeshPart") or instance:IsA("UnionOperation") or instance:IsA("Part") then
local tween = tween_service:Create(instance, TweenInfo.new(0.2, Enum.EasingStyle.Circular, Enum.EasingDirection.InOut), {Transparency = transparency})
tween:Play()
end
end
local function initialize_transparency(obj: Instance)
if obj:IsA("Model") then
for _, child in ipairs(obj:GetDescendants()) do
if not original_transparency[child] then
if child:IsA("BasePart") or child:IsA("MeshPart") or child:IsA("UnionOperation") or child:IsA("Part") then
original_transparency[child] = child.Transparency
end
end
set_transparency(child, 1)
end
else
if not original_transparency[obj] then
original_transparency[obj] = obj.Transparency
end
set_transparency(obj, 1)
end
end
local function toggle_visibility(obj: Instance, is_visible: boolean)
if obj:IsA("Model") then
for _, child in ipairs(obj:GetDescendants()) do
if original_transparency[child] then
set_transparency(child, is_visible and original_transparency[child] or 1)
end
end
elseif original_transparency[obj] then
set_transparency(obj, is_visible and original_transparency[obj] or 1)
end
end
for i, enemy in ipairs(collection_service:GetTagged(enemy_tag)) do
initialize_transparency(enemy)
end
collection_service:GetInstanceAddedSignal(visibility_tag):Connect(function(obj)
toggle_visibility(obj, true)
end)
collection_service:GetInstanceRemovedSignal(visibility_tag):Connect(function(obj)
toggle_visibility(obj, false)
end)