I cant check if my objectvalue.Value is destroyed or not

I’m currently scripting a train signalling system for a roblox game. Im using ObjectValues to store the InBlock and in_block Values for scripting. However I have came across a problem:

when an objectValue.Value gets destroyed, the value stays there. I’ve tried using scripts i’ve seen on the devforum to fix that however whenever i do that the event never fires so i cant delete or check if the value is still there or not

Please help me solve this issue (btw the reason you can see stuff like

signal.state = 0
data.State.Value = 0

is cause if i only update one value, it wont sync between the dictionnary and the Value instance, hopefully i find a better way to do that.) (I also use a boolValue named nilval just so the dictionnary doesnt delete in_block cause its value is nil)

local SIGNALS = workspace.FutureSignalling.Signals
local Sensors = workspace.FutureSignalling.Sensors
local Trains = workspace.Trains
local module = require(game.ReplicatedStorage.FindAncestorModule)
local nilval = workspace.FutureSignalling.False

local signals = {}

local greenColor = Color3.fromRGB(0, 255, 0)
local yellowColor = Color3.fromRGB(255, 255, 0)
local redColor 	= Color3.fromRGB(255, 0, 0)
local blackColor = Color3.fromRGB(0, 0, 0)

--[[ Function to update the state in both the dictionary and the instance A modifier pour que ca devient une fonction generale
local function updateState(child, newState)
    signals[child].state = newState
    local data = child.SignalData
    if data and data:IsA("Folder") then
        data.State.Value = newState
    end
end]]
--workspace.Part.AncestryChanged

function updateColor(signal,data)
	if signal.state == 0 then-- ROUGE
		data.Parent.Green.Color = blackColor
		data.Parent.Yellow.Color = blackColor
		data.Parent.Red.Color = redColor
	elseif signal.state == 1 then -- JAUNE
		data.Parent.Green.Color = blackColor
		data.Parent.Yellow.Color = yellowColor
		data.Parent.Red.Color = blackColor
	elseif signal.state == 2 then -- VERT
		data.Parent.Green.Color = greenColor
		data.Parent.Yellow.Color = blackColor
		data.Parent.Red.Color = blackColor

	end
end


function UpdateSignal(signal, data)
	--changer la couleur du signal
	if signal.advance_signals then
		for _,v in signal.advance_signals do
			if v.SignalData.State.Value == 0 then
				signal.state = 1
				data.State.Value = 1
				updateColor(signal,data)
			elseif v.SignalData.State.Value == 1 then
				signal.state = 2
				data.State.Value = 2
				updateColor(signal,data)
			end
		end
	end		
	updateColor(signal,data)	
end

function EnterBlock(signal, hit, data ) 
	print(signal)
	
	local train = module.FindFirstAncestorInChildren(hit, Trains)
	
	if signal.in_block and data.InBlock.Value == nilval then
		print(train)
		if train then

			signal.in_block = train
			data.InBlock.Value = train
			
			signal.state = 0
			data.State.Value = 0
		end
		
		UpdateSignal(signal, data)
	elseif signal.in_block and data.InBlock.Value == train then
		print("") -- ignore
	else
		warn("TRAIN ENTERING BLOCK WHEN OCCUPIED")
	end
end

function ExitBlock(signal,hit,data)
	local train = module.FindFirstAncestorInChildren(hit, Trains)
	
	if signal.in_block and data.InBlock.Value == train then
		if train then
			signal.in_block = nilval
			data.InBlock.Value = nilval
			
			signal.state += 1
			data.State.Value += 1
		end
	end
	UpdateSignal(signal, data)
	print("la valeur in block est ".. tostring(signal.in_block))
	
end


for _,child in SIGNALS:GetChildren() do
	local data = child.SignalData
	if data and data:IsA("Folder") then
		signals[child] = {
			['enter_point'] = data.EnterPoint.Value,
			['exit_point'] = data.ExitPoint.Value,
			['state'] = data.State.Value,
			['in_block'] = data.InBlock.Value,
			['advance_signals'] = {}
		}
	end
	
	-- read all the advance signals and put it in a table

	for _, v in data:GetChildren() do
		if v.Name == "AdvanceSignal" and v:IsA("ObjectValue") and v.Value and v.Value:IsA("Model") then
			table.insert(signals[child]['advance_signals'], v.Value)
		end
	end
	
	--update when advance signal changes state
	for _,v in signals[child].advance_signals do
		v.SignalData.State.Changed:Connect(function()
			UpdateSignal(signals[child], data)
		end)
	end
	
	
	signals[child].enter_point.Touched:Connect(function(hit)
		
		EnterBlock(signals[child], hit, data )
	end)
	
	signals[child].exit_point.Touched:Connect(function(hit)

		ExitBlock(signals[child], hit, data )
	end)
	
	
	signals[child].in_block.AncestryChanged:Connect(function() 
		if signals[child].in_block:IsDescendantOf(game.Workspace) then
			print("part exists")
		else
			print("part does not exist")
		end
	end)

end


Please help, no one has answered my question so I’m still stuck

Not sure what your asking for exactly but maybe make separate names for each objectvalue.Value and do something like this to check

If game.Workspace:FindFirstChild(objectvalue.Value.Name) then
    — object is there etc..

The solution you tried using used the AnsestryChanged event to detect when the parent of the part changed

When a part is destroyed, it’s parent is set to nil (this is a simple way to check if the part was destroyed). Otherwise, you can use the .Destroyed event to detect when it is destroyed
(The destroyed event is actually somewhat recent, before that, we used to listen change in the parent property, ChildRemoved, etc, …)

Si jamais tu as un peu de mal à lire l’anglais, je peux expliquer les trucs en français, mais pour les besoins du forum, je pense que c’est mieux que ça soit en anglais, il y a probablement un règlement pour

Ive tried doing that, however the event wont print, meanwhile i wrote the same bit of code in another script that listens for another object value well outside of what im coding and it works? i am so confused on these double standards

Building onto what @Tomi1231 said, you could just use :IsDescendantOf() on the object to see if it still exists in the game (still parented to something in the instance hierarchy)

if data.InBlock.Value:IsDescendantOf(game) then
    --runs if the object still exists

Alternatively, you can flip the order and also use :IsAncestorOf() like this:

if game:IsAncestorOf(data.InBlock.Value) then

If events are unstable, you could just append this to every time the object needs to be accessed and ditch .AncestryChanged.

That simply means something is wrong, these inconsistencies always have a reason
I’m thinking either the value is not being destroyed with :Destroy() (in the past, it was common to parent objects to nil, as the :Destroy() method didn’t exist) or you aren’t properly connecting to the event?? (Your code snippet is correct, but the script itself could not be running and other things like that)

Can you show us how the object is getting destroyed?

Eh i had same issue
Either you make temp .Destroying connection (i assume you will change Value)
Or just:

if ObjectValue.Value == nil or not ObjectValue.Value:IsDescendantOf(game) then

end