Idk if you will find any use for this. Honestly I just made this for my own programs.

pastebin get RL3ZUZQM game

use os.loadAPI("game") at top

code

Objects = {["Raw"] = {}}
local Events,LastId = {},0
local EventType = {
[1] = function(i,v)
  if v[2][v[3]] ~= v[4] then
   v[4]  = v[2][v[3]]
   os.queueEvent("Changed",v[3])
  end
end, [2] = function(i,v)
  v[2]()
end
}
CreateInstance = function(key,add)
local obj = {}

local changed = function(prop)
  LastId = LastId + 1
  Events[LastId] = {1,obj,prop,obj[prop]}
  return LastId
end obj["Changed"] = changed

for i,v in pairs(add) do
  obj[i] = v
end

table.insert(Objects.Raw,obj)
Objects[key] = obj
return obj
end Objects.GetChildren = function()
return Objects.Raw
end DisconnectEvent = function(id)
Events[id] = nil
end Attach = function(func)
LastId = LastId + 1
Events[LastId] = {2,func}
return LastId
end
UpdateAsync = function()
for i,v in pairs(Events) do
  EventType[v[1]](i,v)
end
end

my documentation that I made in like 5 seconds


game.CreateInstance(key,table)
-- makes a new object. key is to adress it in game.Objects
game.Objects.keyname.WhateverYouPutInTable
-- the table is full of your properties for example
local Stuff = {
  ["X"] = 42, ["Y"] = 15
}
game.CreateInstance(key,Stuff)
-- then you could do print(game.Objects.X) or game.Objects.Y
-- this also returns the object so you can just do
local Batman = game.CreateInstance(key,Stuff)
print(Batman.X,Batman.Y)
-- newly created objects have events (1 at the moment), called Changed
local UniqueID = Batman.Changed("X") --You have now added a event with a unique id
-- To remove the event just do
game.DisconnectEvent(UniqueId)
-- To use the event do this
Batman.X = 41
while true do
  sleep(1)
  game.UpdateAsync() --add this right before a os.pullEvent
  local event,prop = os.pullEvent()
  print(event,prop)
end
-- Batman.X is supposed to be 42, but we changed it to 41, so now it will print
-- "Changed	X", it prints X too since X was the property that got changed
-- game.Objects:GetChildren() gets all the objects in a table without there key
local x = game.Objects:GetChildren()
for _,v in ipairs(x) do
  print(v.X,v.Y) --this is just an example since Batman is the only object at the moment
end
-- game.Attach(func) this just runs a function every time UpdateAsync is called.
-- it also returns a unique id and can be removed
-- I think I went over everything...

EDIT : Also if you do an object with the same key, it will over write your object in game.Objects, but not in game.Objects.Raw, so GetChildren will still receive that overwritten object and events will continue to work (Also the variable thats returned from game.CreateInstance will work)