I have a bunch of sprites that form ad hoc groups during gameplay, and I need each sprite to have a reference to the group. I implemented the group as a table in the level, but when I went to send this table to the sprites, I get the “Message buffer too small for table” error.
I should think a recursive table is too big, if it’s trying to send the whole table!
I suppose it could just be that it’s trying to send everything up to the recursive points, but regardless, I would much prefer if I could send the table by reference, instead of trying to send the whole thing. Is there a way I could send just a reference to the group instead of the entire group? This group is going to be changing during play, and I only want to update the group once, not the group copy in every sprite.
Well, I suppose I might be able to rethink some of the structure of what needs to know what if I can’t; but this does raise another concern as well: objects in tables are references, right? When I have an object linking to a sprite that also has the group object in a table, which in turn holds a table of sprite objects, which have the group object… We are only talking about one group object and one sprite object here, right? I read somewhere that lua variables are always references, but this table size issue (being more than a single reference to 1 variable) has me a bit concerned.
So I guess that’s two questions: passing a reference to the table, and making sure I’m not making a giant (non)recursive blob even without worrying about messaging.
Yes Lua tables are passed by reference. But when you post a message the table data get serialised into a binary format and at that point each reference to the table will be serialised and take up precious bytes in the message buffer.
It is often the case that the developer uses a shared Lua module to store game state in.
Perhaps this would help in your situation too.
Yes, like Mathias wrote, store the state in a Lua module, keyed by some kind of group id, and only send the group id in the messages.
Here’s an example with a “grouper” module that tracks groups and objects belonging to groups.
-- grouper.lua
local M = {}
local groups = {}
local count = 0
-- create a group
-- @return id of the created group
function M.create()
local group_id = hash("group"..count)
local group = {
id = group_id,
objects = {},
}
groups[group_id] = group
return group_id
end
-- add an object to a group
function M.add(group_id, object)
local group = groups[group_id]
assert(group)
group.objects[#group.objects + 1] = object
end
function M.remove(group_id, object)
local group = groups[group_id]
assert(group)
local objects = group.objects
for i=1,#objects do
if objects[i] == object then
table.remove(objects, i)
return true
end
end
return false
end
function M.get(group_id)
local group = groups[group_id]
assert(group)
return group.objects
end
return M
Here’s an example of how it can be used:
-- foo.script
local grouper = require("grouper")
local function leave_group(self)
if self.group_id then
grouper.remove(self.group_id, go.get_id())
end
end
local function join_group(self, group_id)
self.group_id = message.group_id
grouper.add(message.group_id, go.get_id())
end
function init(self)
-- create a group and add this game object to the group
self.group_id = grouper.create()
grouper.add(go.get_id())
-- some kind of movement direction
self.direction = vmath.vector3()
-- raycast 100 pixels in front of the object
-- if we hit something we bring it to our group
local raycast_groups = { hash("objects") }
timer.delay(0.5, true, function()
local from = go.get_position()
local to = from + self.direction * 100
local hits = physics.raycast(from, to, raycast_groups)
if hits then
for i=1,#hits do
-- send a message to the object we hit that it should join our group
msg.post(hits[i].id, "join_group", { group_id = self.group_id })
end
end
end)
end
function final(self)
-- remove the object from the group it belongs to
leave_group(self)
end
function update(self, dt)
-- apply some kind of steering behaviour and movement logic
end
function on_message(self, message_id, message, sender)
if message_id == hash("join_group") then
leave_group(self)
join_group(self, message.group_id)
end
end
2 Likes