Jump to content

Auto generated UUIDs on Entities


martyj
 Share

Recommended Posts

  • 1 month later...
What if you load two copies of a prefab? Will they have the same entity ID?

 

I'm assuming he means an instance ID where each instance has a unique ID. Usually an int/long value or a GUID type of ID I guess too. Memory addresses aren't generally given a dual purpose.

 

However, I'm not sure this is really needed. I think I've asked for this a long time ago as well but honestly anything that I need to do something in code with should have (in my view) a unique name anyway. I then just get it by it's unique name.

Link to comment
Share on other sites

I agree with Rick about the unique name. My problem is how many unique things I have to create.

 

In my game, every tree has the ability to cut it down. Every NPC has their own conversation. Every door is usable.Every block of water is fish-able,

 

The name field works fine if you're working on smaller projects. When you're 1000 hours into a project, it is a lot of extra time to have to name an entity every time you want to interact with it.

 

As far as pre-fabs goes, they wouldn't have a UUID until you added them to the map. I'm only talking about entities saved into the map should have their own UUID.

 

This requires is basically an extension to the "name" field. Without a developer having to give an entity a name each time.

Link to comment
Share on other sites

Every tree in our game can be cut down too but it doesn't need a unique ID for that. You pick the tree and that gives you the entity and you can access it's script if you need to. Can you give an example as to why you are wanting a UUID for a tree to chop down?

 

 

The key really is everything you interact with is pretty much done through some kind of pick to get that entity. There is little need, for the most part, to loop over entities so you don't really need to find them to do that. If you do then attach a script and use that, but picking is generally, in most games, the way to get an entity to do something with.

Link to comment
Share on other sites

I'm just curious as to why you need the name of a tree. What I said should stand in C++ too (minus a script). If you are attaching functionality to trees then having the name "tree" should be enough I would think. You're stick doing a pick in C++ to get what tree the player is trying to chop down right?

 

I'm just trying to help to show how we get by without needing the name that much.It's hard without a use case and specifics though. I was in your same boat but I found that I don't need the name much and only for a few things even when I have a ton of things in my scene that the player can interact with. There are maybe other ways to handle it.

 

I can see if you are doing a multiplayer game and the player picks on teh client and you need to tell the server what tree id it is.

Link to comment
Share on other sites

In C++ the only way to get an entity is to search it by a name.

 

I'm not doing a Pick.

 

I register the entity in C++, attach it to my own custom code, then when I do a pick, I get the object's UserData to cast it to an object to do things like damage to a tree.

 

It's where I register the object from Leadwerks to C++ is where I need the UUID.

Link to comment
Share on other sites

OK, so what I can gather is that your issue is after the map loads you loop through all entities to figure out what C++ code to attach to. But where does a unique name really come into this and what is an ID going to solve with this? You're only giving me pieces of your logic here so it's hard to really show an alternative method to what you are doing.

 

Tree names obviously just need the name "tree" in them for you to know to attach your tree code to a tree entity. Once it's in a list then you don't need an ID for it because you mentioned that when a player does a pick that's how you get the entity and the code for it. So no ID required there right? What am I missing with that flow? Can you give me an example of needing an ID for a tree so I can help further because right now there is little need for an ID in a singleplayer game that I can see.

Link to comment
Share on other sites

My entities have a property to them to know which c++ class to instantiate.

 

Since you can't pass entities from Lua to C++, I pass the entity name instead. This is where I want a UUID.

 

I loop through all the entities in the world, and find the entity with that name. Then I instantiate a custom C++ class with that found c++ Entity.

 

 

 

Another use case for not-so-distant future reasons.

 

-----------------

 

An NPC will have a list of conversations, As every NPC will have their own custom conversations and every NPC can be spoken to, the entities will need to find a conversation for their specific instance.

Link to comment
Share on other sites

My entities have a property to them to know which c++ class to instantiate.

 

Since you can't pass entities from Lua to C++, I pass the entity name instead. This is where I want a UUID.

 

I loop through all the entities in the world, and find the entity with that name. Then I instantiate a custom C++ class with that found c++ Entity.

 

A unique ID isn't what you're using then with that system. You're attaching a key/value of say "type" = "tree". That's fine and this isn't a unique ID right?

 

 

An NPC will have a list of conversations, As every NPC will have their own custom conversations and every NPC can be spoken to, the entities will need to find a conversation for their specific instance.

 

Shouldn't every NPC have a unique name anyway though? I mean you'll have Bill Cloudsmith, and Emily Smith, etc?

Link to comment
Share on other sites

I am using a "unique ID", or the entity name at the moment to find the entity in C++ from Lua. Since leadwerks is lacking in the Lua to C++ department I believe this is the only way to get an entity from Lua to C++. You can't call C++ functions passing in a Lua entity object as it won't be a C++ entity.

 

You have to pass an identifier in Lua then search the C++ entities for the identifier.

 

Which is why I want a UUID field so I don't have to keep creating custom names. UUIDs are also harder to guess, for multi-player security purposes.

 

 

Every NPC should have a unique name and I concur, but what about fishing spots, trees, mining rocks, ect? They will need a unique name as well just for the Lua to C++.

Link to comment
Share on other sites

Which is why I want a UUID field so I don't have to keep creating custom names.

 

So are you saying you are naming things like "tree1", "tree2", "tree3", etc?

 

 

You mentioned before you are using C++. I assume you're using C++ for everything code related and not using Lua code at all?

 

You mentioned using the user data when picked to get the C++ class instance you attached to the entity after the map is loaded and you cycled through the entities I assume?

 

 

If I was using C++ code only and I needed tree's here is what I'd do (have done).

 

 

1) create map with trees in them and name them all "tree"

2) load map

3) loop through entities and when the entity name is "tree" create an instance of my Tree class (which is derived from my own GameObject class which has virtual functions for the LE callback functions like Update, Draw, etc)

4) assign that instance of the Tree class to my userdata of the tree entity

5) set the engine functions for this entity (Update, Draw, etc just like lua is doing)

6) inside these C functions get the entities userdata and cast it to GameObject and call the virtual functions (now you have behavior just like lua entity scripts do but in C++)

5) when picking a tree, get the picked entities user data, cast to GameObject, and call it's Pick function (another virtual function of GameObject).

6) What whatever you want inside the Tree's Pick function.

 

 

So the reason I'm asking all these question is because nowhere in there do I need to have a unique name for any of the trees. So I'm confused as to why you say you do.

 

Take multiplayer out of this because LE isn't setup for that now so you have to do all of that yourself anyway. In that case it makes sense to have unique ID's because when the user picks a tree, you have to tell the server that somehow and the ID would be how you do that.

 

If you are mixing C++ and Lua you can pass LE entities between them in function calls. Josh does this with callbacks like ForEachEntityInAABBDo(), and other calls.

 

So this is why I'm confused. What above won't work in your situation?

Link to comment
Share on other sites

@Rick. Here is an example of a Lua script that I use. This is basically the only Lua I use in LE.

 

Script.className = "" --string "Binding C++ Class"
function Script:Start()
RegisterClass(self.entity:GetKeyValue("name"), self.className);
end

 

 

I've tried sending self.entity instead of the name, but it gives access violations. So I pass the name to loop through entities to find entities with a specific name.

 

At the moment I am naming things like tree1, tree2, tree3, tree4... In the future this will be a very bad idea.

 

I have a map class which I add Strings -> Static C functions to create dynamic objects. Such as "OakTree" => OakTree_Init(Entity* entity);

 

The code to register is as follows

 

 

int Binder::RegisterClass(lua_State* L)
{
 const char* entityName_cstr = lua_tostring(L, 1);
 const char* className_cstr = lua_tostring(L, 2);
 if (entityName_cstr == NULL)
 {
  entityName_cstr = "";
 }
 if (className_cstr == NULL)
 {
  className_cstr = "";
 }
 string entityName(entityName_cstr);
 string className(className_cstr);
 Entity* entity = NULL;
 App* app = App::GetApp();
 World* world = app->world;
 std::list<Entity*> entities = world->entities;
 if (entityName.length() == 0 || className.length() == 0)
 {
  goto error;
 }
 for (std::list<Entity*>::iterator it = entities.begin(); it != entities.end(); ++it)
 {
  Entity* ent = *it;
  if (ent->GetKeyValue("name") == entityName)
  {
   entity = ent;
   break;
  }
 }
 if (entity == NULL)
 {
  goto error;
 }

 for (std::map<std::string, MODEL_CTOR_FUNC>::iterator it = ctors.begin(); it != ctors.end(); ++it)
 {
  if (it->first == className)
  {
   WFModel* model = it->second(entity);
   model->AddHooks(); // Update/Delete hooks
   Binder::models.push_back(model);
   lua_pushboolean(L, true);
   return 1;
  }
 }

 error:
 lua_pushboolean(L, false);
 return 1;
}

 

As far as your method mentioned above, I've never really thought of that tbh :P.

 

Either way, for networking type of purposes, I will need a unique name on each entity to pass data on objects. Such as Player1 cut down Tree XXYYZZ.

Link to comment
Share on other sites

Either way, for networking type of purposes, I will need a unique name on each entity to pass data on objects. Such as Player1 cut down Tree XXYYZZ.

 

Until networking comes about you won't get around having to do this yourself (and maybe then depending on how Josh does it). If tree's can be chopped it makes them more than static entities which means the server needs to control them (create them and distribute them to the clients). Servers won't have the gfx capabilities to even run a leadwerks game so your server app can't be a leadwerks app. It has to be a plain C++ application. So you have to do this yourself in that app anyway.

 

 

That's an interesting way of doing it. I've never thought of that way. It seems a little inefficient when compared to just looping over the entities from C++ once the map is loaded as you are going back and forth from lua to C++ a lot based on all the entities you have in your scene. If you wanted to continue doing this I would think you for sure can pass the actual self.entity since there are LE functions where you can do this and it works fine. Probably just need a post on how that's done. Someone has probably done it besides Josh but maybe Josh could share what he's doing to get that to work. Maybe he has a function in the Interpreter class that helps get the entity passed in.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...