I initially found this behaviour in a project of mine, and proceeded to isolate the problem through a test program. The test's code is as follows:
````cpp
class TestClass
{
public:
TestClass();
void run();
private:
entt::registry registry;
entt::entity entityA;
entt::entity entityB;
};
TestClass::TestClass()
: registry()
, entityA()
, entityB() {}
void TestClass::run()
{
std::cout << (this->registry.valid(this->entityA) ? "Entity A is valid." : "Entity A is invalid.") << std::endl;
std::cout << (this->registry.valid(this->entityB) ? "Entity B is valid." : "Entity B is invalid.") << std::endl;
this->entityA = this->registry.create();
std::cout << (this->registry.valid(this->entityA) ? "Entity A is valid." : "Entity A is invalid.") << std::endl;
std::cout << (this->registry.valid(this->entityB) ? "Entity B is valid." : "Entity B is invalid.") << std::endl;
}
int main()
{
TestClass testClass{};
testClass.run();
}
````
One should expect that the output be:
Entity A is invalid.
Entity B is invalid.
Entity A is valid.
Entity B is invalid.
However, the actual output is:
Entity A is invalid.
Entity B is invalid.
Entity A is valid.
Entity B is valid.
which is not what we expected. To fix the problem, we have to initialize the entities in the class to entt::null. Why do we have to do so? Is this expected behaviour or is it a bug?
This happens because you default initialise entities which gives them values equivalent to 0 which is a valid entity identifier in general. When you first test for the validity you get "entity invalid" result because no entities have been created thus far. Later on, when you actually create an entity it gets identifier 0 and thus your default initialised entities become valid.
If you want to store entities in variables that should be invalid by default and only initialised later you should use entt::null for initialising those variables:
class TestClass
{
public:
TestClass();
void run();
private:
entt::registry registry{};
entt::entity entityA{entt::null};
entt::entity entityB{entt::null};
};
As @Innokentiy-Alaytsev correctly pointed out, entt::entity e{}; isn't the null entity. Instead, it's a potentially valid one (in short, entity 0).
So, yes, using entt::null is the intended way to initialize your data members. It's definitely not a bug and somewhat the reason for which entt::null exists. 馃檪
@Innokentiy-Alaytsev, I see. Thanks!
@skypjack, why aren't entities initialized to entt::null by default?
why aren't entities initialized to entt::null by default?
Because entt::entity is an enum and as such it doesn't have a constructor or the like that would allow it to be given a default value. It's as if you want to give a default value to an int at construction time, the only way to do this is to assign the value to the variable.
However, it's easy to define your own entity type as a class and use it with the registry. There is an example here if you're interested.
@skypjack: Ah, so it gets defaulted to something equivalent to 0 instead. And letting 0 be equivalent to null might break projects, based on the issue I've read about introducing a entt:null entity type. Thanks!
I don't have a reason yet to create my own entity type and I'm fine with instantiating entity variables to entt::null on class construction, but thanks anyway for making me aware of the feature. It might come in handy in the future.
I'm glad to help. Let me know if you have any other doubt.
I also invite you to join the gitter channel or the discord server (link in the README) for a more direct discussion in future. 馃憤
I'm closing this issue because I think it has been asnwered. Feel free to continue the discussion here if needed or to reopen it.