Problem with removing table values

I am currently having a problem with figuring out how to remove a value from a table in Roblox Studio. It seems although some code isn’t understanding an update in the table, whilst other code is printing a successful removal in an item from a table.

I have looked into many similar topics, and most of the solutions come down to: “have you tried “Table[Item] = nil”?” Yes. I tried that before I even looked into other dev forum posts relating to my problem. I’ve even talked to Chat GTP many times without a proper solution being given.

Summary of the code (code below): I am making a horror game, and I have a bear (the monster) roam around randomly selected walk points in the map. These walk points are determined by parts I place around the map, and the code grabs a random part from a folder of these parts and gives the bear the position of this randomly selected part (the walk point). The bear will select a walkpoint to move to after finishing walking to a previous walk point. Here’s the problem. If the bear randomly selects a walkpoint it’s already on the exact position of, it will send the bear to Vector3.new(0,-10000000,0). Basically, the bear is sent to nill.

The full lines of code are very large, but the only relevant lines of code are:

(1) The code that includes the table, last target, current target, and the tween that makes the bear move between them.

                    local AvailableFolder = workspace.BearWalkPoints:GetChildren()

					if LastTarget then
						print(type(AvailableFolder))
						
						if type(AvailableFolder) == "table" then
							print("Table")
							-- Remove LastTarget from the AvailableFolder table
							for index, walkPoint in ipairs(AvailableFolder) do
								if walkPoint == LastTarget then
									print("Remove!")
									table.remove(AvailableFolder, index)
									break -- Exit the loop once the item is removed
								end
							end
							
						end
					end
					
					
					print(AvailableFolder)
					local RandomWalkPoint = AvailableFolder[math.random(1, #AvailableFolder)] --grab a walkpoint
	
					local MovePoint = RandomWalkPoint.Position
					
					
					local Target = MovePoint -- Target variable for other purposes
					
					
					
					if CanClosest == false then
						CanClosest = true
			
						
					elseif CanClosest == true then
						CanClosest = false
	
					end
					
					if Running == true and math.random(1,2) == 1 and CanClosest == true then
						print("closest player")
						Target = BearPosclosestToPlayer(AvailableFolder)
						

					end

					if Angermode == true then --and CanClosest == true then
						Target = BearPosclosestToPlayer(AvailableFolder)
					end
					
					
					
					Target = Target + Vector3.new(0,3.5,0)
							
					print(Target)
								
					BearRoot.CFrame = CFrame.lookAt(BearRoot.Position, Target) 
					
						
					LastTarget = RandomWalkPoint
				
					local CanWhileBear = true
					local CanTweenPlay = true
						
					local miniRayDistance = -6
					
					local distance = -100
					local speed = 9 * (distance/100) -- normally 9 * ...

					if Angermode == true then
						speed = 4 * (distance/100)
					end

					local BearSpeed = (Target - BearRoot.Position).Magnitude
					local BearWalkTime = BearSpeed * speed / distance
					
					local moveInf = TweenInfo.new(BearWalkTime, Enum.EasingStyle.Linear)
					local moveGoal = {Position = Target}
					local MoveTS = Tweenservice:Create(BearRoot, moveInf, moveGoal)
					
					MoveTS:Play()

(2) How the closest walk point is determined

local function BearPosclosestToPlayer(Table)
local NearestWalkPoint, NearestPointMagnitude
local PointMagnitude

for i, v in Table do
	if NearestWalkPoint then
		PointMagnitude = (RootPart.Position - v.Position).Magnitude

		if PointMagnitude < NearestPointMagnitude then
			NearestWalkPoint = v
			NearestPointMagnitude = PointMagnitude
		end
	else
		NearestWalkPoint = v
		NearestPointMagnitude = (RootPart.Position - v.Position).Magnitude
	end
end

print(NearestWalkPoint.Position)

return NearestWalkPoint.Position
end

How have I tried to fix this? I have tried to fix this by creating a system that holds the walkpoints in a table that the bear will randomly select from. The table will remove the last walk point, so that the bear is not allowed to select the position it is currently standing on when selecting a new walk point. The code seems although it won’t let me remove the last walkpoint from the table; as it will repeatedly act although the last walkpoint is still in the table, even after a print shows it is no longer in the table.

I apologize, as this is quite a length report. Any help is appreciated, thank you!

Try removing your previous target from the table after the bear finishes moving to its target. It’s possible the reason it doesn’t exist is because the very first time this code runs, you don’t have a LastTarget set, thus nothing is removed from the table.

I could’ve read it wrong, but that’s my guess at the moment. Still looking at it.

Thank you very much, for the response.

I do not believe that is a problem and I believe that would cause more problems because I need the LastTarget check to happen before the Target is specified, and I make sure that I don’t accidentally check for a nil value (as it is nil before it is set in the code).

I am currently adding an update to this in a reply to my original message (which is why I now know what you said probably isn’t a problem) and I have found a new problem and “fixed” the old one. I am surprised this happened because I’ve spent many hours working on this, and it seems although for pure irony the universe has given me a possible look into a solution only 12 minutes or so after posting on the dev forumn. again, it means very much to me that you even responded in the first place. Thank you!

No problem! I do know that one thing you could do to shorten the loop is by using table.find then table.remove. Assuming you don’t have duplicate values in the table table.find will find the first instance, then you can just use that index and remove it.

UPDATE: Alright. I added a new line of code that seemed to work this time. Like I have stated before, I have tried “insertablevalue[insertobjectvalue] = nil” in the past. Although, in the past, I would combine it without a loop or by itself using something along the lines with “table.find()”. This time, i combined it with table.remove() in the loop I have in the code and it now reads

AvailableFolder[walkPoint] = nil
table.remove(AvailableFolder, index)

now, this has caused the bear to go through not one-- but TWO walk points! AHAH! Now, the bear finds the closest walkpoint to the player, finds the second closest walkpoint, and then tries to walk back to the closest walkpoint-- upon walking back to the player a second time the bear will be sent to nill. Now, it seems to be for a different reason than before. That’s a massive sigh of relief. Lol.

The prints I run with “print(AvailableFolder)” now read:

i = 1
37 items (What I want, bear walks to closest position to player)
All walkpoints included

i = 2
36 items (What I want, bear walks to second closest position to player)
All walkpoints included except for bear’s current walkpoint

i = 3
36 items (What I want, bear walks to the first closest position to player)
WHAT I THINK: All walkpoints included except for bear’s current position

i = 4
36 items (It seems to be what I want… bear walks back to closest position to player)
WHAT Should be happening: bear walks back to player successfully, goes back to second cloest
What is happening: bear walks back to player successfully, then teleports to nill
what I think is happening code-wise: the bear is for some reason not updating the table?

I’m still running bug-tests as we speak, so I’ll update yalls if I see anything more and or fix it…

NEVERMIND AGAIN it seems that it went back to how it was at first WAHT IS HAPPENING AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA :sob:

So, what you’re trying to do is table[key] = nil. This works for dictionaries because dictionaries don’t have indices, they have key/value pairs. You’re using an array (ordered list, :GetChildren() returns an array), which is ordered through indices, so you can’t remove it by trying to access a key, and you can’t do table[index] = nil because then the index would just hold the value of nil (since the index itself isn’t being set to nil).

local tab = {"a", "b", "c", "d"}
print(tab)
local indexToRemove = table.find(tab, 3)
table.remove(tab, indexToRemove)
print(tab)

You could essentially implement the above to shorten your loop. Use table.find to find the index at which your part is being stored, and then use table.remove to remove it from your table.

Edit: this might also solve your problem with the walktopoint not being removed

Thank you very much, I will try this!

I hope it works. Here’s a look at it:
image

Whoops made it look a little confusing. You can replace table.find(tab, 3) with table.find(tab, "c") incase you don’t know the actual index

Wait, how would I find the number of my target in table.find(tab, 3)?

The code I wrote is:

                    if LastTarget then
						local ToRemove = table.find(AvailableFolder, LastTarget)

						table.remove(AvailableFolder, ToRemove)						
					end

i’m testing this right now, but if I did “table.find(AvailableFolder, LastTarget)” incorrectly, please tell me. My next guess would be to say “table.find(AvailableFolder, #LastTarget)” if this bug test im doing rn doesn’t work. OOPS i just read what you said

Yeah sorry I put that wrong. I was trying to edit before you replied lol.

So you could store the point you want to remove with table.find(yourTable, point) and it’ll find the index.

1 Like

Yeah that looks like it should work

Unfortunately, it didn’t work. The bear still teleports to nill after the first walkpoint is completed.

I apologize, as I am going to eat dinner; as I am shortly leaving for an activity. When I return, I will continue to respond to this. Thank you very much for your help, I do appreciate it very much!

No problem. I’ll look at it some more. I will clear up the mistake I made above in the meantime since it can cause more confusion.

table.find(tab, 3) was incorrect, I didn’t mean to put the index of 3 in there. The second argument for table.find is the value you want to find, not the index (since the purpose of this is to find the index the value is at). That’s why I was changing my example to table.find(tab, "c"). The mistake I made would’ve returned nil (since there’s no value of 3 in the table), whereas the correct one returns 3, because “c” is at index 3.

If you have a table that looks like this (which is a dictionary):

local myTable = {["Health"] = 100, ["Speed"] = 10}

Then you could do myTable["Health"] = nil to remove health from the table, for example. But yeah, GetChildren returns an array, which will look like the table of letters above (except in your case the letters are parts).

Why don’t you exclude the current walkpoint when you search for a new one?

local function BearPosclosestToPlayer(Table, ExcludeWalkpoint) --> add an exclude parameter
	local NearestWalkPoint, NearestPointMagnitude
	local PointMagnitude

	for i, v in Table do
		
		-->> don't check the walkpoint it's already on
		if v == ExcludeWalkpoint then
			continue
		end

		if NearestWalkPoint then
			PointMagnitude = (RootPart.Position - v.Position).Magnitude

			if PointMagnitude < NearestPointMagnitude then
				NearestWalkPoint = v
				NearestPointMagnitude = PointMagnitude
			end
		else
			NearestWalkPoint = v
			NearestPointMagnitude = (RootPart.Position - v.Position).Magnitude
		end
	end

	print(NearestWalkPoint.Position)

	return NearestWalkPoint.Position
end

Oh. That’s a good idea. I’ll try it right now, thanks!

alright, so the proposed solution kind’ve works… here’s the problem

I put a print to make sure that the “if v == Exclude” is actually passing, and it is. But, for some reason, it seems although the code isn’t skipping that loop that we want it to skip. The return variable is still the exclude object. I don’t know why. I’ll run some more testing. Thank you!

Can you show the current code? What prints in the output?

Yes. My current plan is to quadruple check and make sure there are no duplicate parts that hold the same position, but here is the code. I added a few more checks and they still aren’t working.

local function BearPosclosestToPlayer(Exclude)
local NearestWalkPoint, NearestPointMagnitude
local PointMagnitude

for i, v in BearWalkPointFolders do
	
	if Exclude and v.Position == Exclude.Position then
		print("They're the same...")
		
		continue
	end
	
	if NearestWalkPoint and v ~= Exclude then
		PointMagnitude = (RootPart.Position - v.Position).Magnitude

		if PointMagnitude < NearestPointMagnitude then
			NearestWalkPoint = v
			NearestPointMagnitude = PointMagnitude
		end
	else
		if v ~= Exclude then
			NearestWalkPoint = v
			NearestPointMagnitude = (RootPart.Position - v.Position).Magnitude
		end
	end
end

print("Loop Result:")
print(NearestWalkPoint.Position)

return NearestWalkPoint.Position
end

The print that checks if the variables are the same in the loop does print successfully. Very strange.