Hum⦠set_name() is interestingā¦
We have a API reference (Built-ins) | Defold function,
can we hash_to_hex(gameobject_id) and then
hex_to_hash it back some way?
I think a gameobject id is a hash which is userdata, can we go back to it from a hex string value?
I still dont understand whatās a hash() internallyā¦
I also looked into this topic, but concluded that there is currently no way to convert a hash back into a string (it might work in the simulator, but it doesnāt work in the actual build).
Right now, I use a JSON data file for each objectāwhich is actually exported from a physics editor I use. It stores URL strings, and I can find the game object via a collection.
Thanks⦠I have gone to another solution, as maintening a body => gameobject id table mappingā¦
BUT I am facing an unsolvable problem:
It seems that 2 handle of the same body are equals with respect to == operator, but they cannot be used as table keys, because they are never equals!!
You can do that
-- given an body handle:
local mytable = { [body] = 1,
[ b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id) ] = 2,
test = (body == b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id) )
, a=1, a=2 }
and youāll get:
{ -- <table: 0x02bd44a9d9d0>
a = 2,
test = true,
[<Box2D.b2body = 0x02bd44a56640>] = 1,
[<Box2D.b2body = 0x02bd44a9dc70>] = 2
}
so⦠here the āaā key is defined twice.. but result in the last value only, because it is the very same key.
The ātestā is true because the body and its reference going from body => shapes => body are equal with the == operatorā¦
BUT I have 2 different entries with <Box2D.b2body> keys that are judged to be not equal to each otherā¦
How is this possible?? Am I missing something here? How do you build a lookup table with body handles as keys?
My module that register body to gameobject mapping just wont work because of this.
I just want to store : my_map[body]=go_id
then : local go_id = my_map[body]
but I never find the go_id because the keys are never equalsā¦
Iāve seen a few comments here; perhaps `get_userdata` will work in the future.
Iām not sure what you are trying to do here, but if you just want to store my_map[body]=go_id you could do it inside the object init function for the objects you try to register and send the data to the module so you can query from other objects or whatever you want to do with it⦠go.get_id(path) should allow you to get the id from the object itself.
b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id) ] = 2,
test = (body == b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id)
i donāt understand what this is trying to achieve but if you look at the output it prints from the end of your mytable variables to the start, so in your example it gives you the overwritten a value, shows you that test is true even if the body and b2d.shape might be different. You need to look at the method that performs the equality check, because it might not work the way you expect. Custom object equality can be implemented to compare only specific parameters (or a subset of them) instead of requiring every property or only the ID to match . and then it prints `[body] = 1,[b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id) ] = 2,` in reverse order so you probably have a body you already extracted and saved in the [body] = 1 but its not the same one as the one using b2d.shape because you have different hashes.
But your issue might be because b2d.body.get_shapes() returns a table with the collision body inside of it and you use the table as a Key for the map, and then above Iām guessing that [body] = 1 uses the this table as a Key and not the body you got from b2d.shape.get_body. Or something similar where you reach a scenario with different objects as keys so the printed reference differs.
Also on your previous question about `hash()`, itās a hashing function that generates a hash value from the input (look at SHA algorithm if you need a better explanation). The game engine uses this hash to index objects for faster lookup, since hash table lookups are typically O(1) on average. Lua tables are implemented as hash tables, which is also why table lookups are generally very fast.
@Eduard was faster here to answer!
Yes, hash() produces simply a number, with a guarantee that the same word produces the same number always. Hashed value is smaller than strings (uint64_t), easier to parse in engine and faster to compare (Hash function - Wikipedia) and gives near-constant access time. It is though a one-way encryption, so you can convert string to hash, but the other way around it doesnāt get back to the original string - hash_to_hex() returns only a hex representation. Reason for this is hash collision, we are using a non-cryptographic hash function (but there is 2^64 possibilities, so worst-case scenario is rare, it grows with strings amount, e.g. for 100k names there is something like one in billions collision chance, but for 1M names, there is something like one in millions).
My reasoning wasā¦
that the engine creates a b2dshape for the placeholder shape and stores the handle for future use. In the original physics functions, you could modify a shape but not delete it. Hence the engine expects the handle to remain valid for the objectās entire lifetime. If you delete it, the crash happens because itās looking for something that no longer exists.
Thanks for your feedback.
For this part:
body == b2d.shape.get_body(b2d.body.get_shapes(body)[1].shape_id
It was just an example, that illustrate that body handles returned by b2d API cannot be used as table keys because equality as table keys dont work. I think this is related to how the userdata metatable is implemented.
If you do this:
local body = b2d.get_body('#collisionobjevt')
local shapes = b2d.body.get_shapes(body)
local shape_id = shapes[1].shape_id -- get first shape handle
local body2 = b2d.shape.get_body(shape_id) -- get the body back from the shape. You expect body ==body2, because it is the same body!
print(body==body2) -- true
-- then table lookup should work:
local map = {}
map[body] = true
-- get ot back via body2
print(map[body2]) -- nil!
=> so yes it must comes from the userdata implementation of these b2d handles.
Ok, so weāre closing our next Community Challenge! ![]()
Maybe there werenāt many participants, but the amount of discussions, feedback and issues found during the challenge will help us improve on this - thank you so much! ![]()
Our prizes go to @Andrew_Fowler and @Eduard - congratulations and thank you for your entries! ![]()
Best Box2D API Showcase - @Eduard for the Box2D Playground
Best Physics Experiment - @Andrew_Fowler for the Hill Climb like experiment
Best First-time Entry - @Andrew_Fowler for the Marbles in a bucket
