BulkMoveTo table-changes are causing my crash?

I’m going to be having a lot of moving objects in my game, moved via CFrame. I’ll be using BulkMoveTo as it’s noted as being the fastest method of updating large amounts of objects.

I have created a module that registers an object, and returns a reference to its index within the table.
I can now use this index to update the CFrames, or to remove it.

I add an Update function inside this module to call workspace:BulkMoveTo() on the tables it has stored within itself at the end of .Heartbeat

This seemingly works for a very small amount of objects. But whenever it grows slightly, any removals crash roblox.
This only appears to happen while Update is also being called in the code (Commenting it out seems to result in no crashes.)

ReproBulkMoveBug.rbxl (25.9 KB)

BulkMove Module
local BulkMove = {}

local Objects, CFrames = {}, {}

function BulkMove.AddToList(Object, CF)

    local Placement = 0

    for i, _ in pairs(CFrames) do

        Placement = i

    end

    Placement += 1

    table.insert(Objects, Placement, Object)

    table.insert(CFrames, Placement, CF)

    --print(#Objects, #CFrames)

    return Placement

end

function BulkMove.UpdateCFrame(ID, CF)

    CFrames[ID] = CF

end

function BulkMove.RemoveItem(ID)

    print("Removing;", ID)

    CFrames[ID] = nil

    Objects[ID] = nil

end

function BulkMove.Update()

    workspace:BulkMoveTo(Objects, CFrames)

end

return BulkMove

All code is found within the PlayerScripts, tapping the button will create a new ExampleObject.

I don’t know if this is a legitimate bug, or if this is something I’ve overlooked in my coding.

try using table.remove in your .RemoveItem function instead of manually setting the index to nil.

function BulkMove.RemoveItem(ID)

    print("Removing;", ID)

    table.remove(CFrames, ID)

    table.remove(Objects, ID)

end

I’ve moved from making the indexes nil, as that appears to be what is making the call cranky. It’s a shame, as I was hoping to avoid needing to constantly create entries.

The module now reads as such;

BulkMove Module
local BulkMove = {}

local Objects, CFrames = {}, {}

function BulkMove.RegisterObjectCFrame(Object, CF)

    table.insert(Objects, Object)

    table.insert(CFrames, CF)

end

function BulkMove.Update()

    workspace:BulkMoveTo(Objects, CFrames)

    table.clear(Objects)

    table.clear(CFrames)

end

return BulkMove

So now rather than altering an entry in a table and editing it once per frame;

  • Frame starts
  • I perform some function that calls to RegisterObjectCFrame
  • I do this X times
  • At the end of the frame, I call Update. This updates everything + clears the table, ready for the next frame.

Now the table only holds what needs to be updated.