Skip to content

Game crash when calling CreateEntityQuery #68

@fire7d

Description

@fire7d

What is the game you are using with IL2CPP Resolver?

VRising

Details:

First of all, I probably don't have basic Unity knowledge - it's my first project of that type, I think it's good opportunity to learn something. The code might be messy, but I've tried "everything" (chatgpt, reading issues etc.) to make it work.

I'm getting the ComponentType using Unity.Entities.ComponentType$$ReadOnly of ProjectM.PlayerCharacter as an argument. Then create ComponentType[] from it (for later to use in CreateEntityQuery method).

Signature is:

      "Address": 152573728,
      "Name": "Unity.Entities.ComponentType$$ReadOnly",
      "Signature": "Unity_Entities_ComponentType_o Unity_Entities_ComponentType__ReadOnly (System_Type_o* type, const MethodInfo* method);",
      "TypeSignature": "iii"
		auto createEntityQueryMethod = IL2CPP::Class::Utils::GetMethodPointer(EntityManagerClass, "CreateEntityQuery", 1);

		// Get the static method ComponentType.ReadOnly(System.Type)
		void* readOnlyMethod = IL2CPP::Class::Utils::GetMethodPointer(ComponentTypeClass, "ReadOnly", 1);

		// Get the System.Type for PlayerCharacter
		Unity::il2cppObject* playerCharacterType = IL2CPP::Class::GetSystemType(PlayerCharacterClass);

		// Call ReadOnly(Type) -> returns boxed struct or object
		Unity::il2cppObject* componentTypeObject = reinterpret_cast<Unity::il2cppObject * (*)(Unity::il2cppObject*)>(readOnlyMethod)(playerCharacterType);

		// Create an array of ComponentType
		Unity::il2cppClass* componentTypeArrayClass = il2cpp_array_class_get(ComponentTypeClass, 1);
		Unity::il2cppObject* componentArrayRaw = il2cpp_array_new(componentTypeArrayClass, 1);

		// Treat the array as array of il2cppObject* (ComponentType is a struct, so likely boxed)
		auto componentArray = reinterpret_cast<Unity::il2cppArray<Unity::il2cppObject*>*>(componentArrayRaw);
		componentArray->At(0) = componentTypeObject;

Then I'm getting all the worlds from it's static field Unity.Entities.World - s_AllWorlds. Then I'm iterating through all the worlds, getting their names, type (just for debug I think, I don't really need that) and most important - EntityManager.

Signatures are:

      "Address": 24345088,
      "Name": "Unity.Entities.World$$get_Name",
      "Signature": "System_String_o* Unity_Entities_World__get_Name (Unity_Entities_World_o* __this, const MethodInfo* method);",
      "TypeSignature": "iii"

      "Address": 151810688,
      "Name": "Unity.Entities.World$$get_WorldType",
      "Signature": "int32_t Unity_Entities_World__get_WorldType (Unity_Entities_World_o* __this, const MethodInfo* method);",
      "TypeSignature": "iii"

      "Address": 151813760,
      "Name": "Unity.Entities.World$$get_EntityManager",
      "Signature": "Unity_Entities_EntityManager_o Unity_Entities_World__get_EntityManager (Unity_Entities_World_o* __this, const MethodInfo* method);",
      "TypeSignature": "iii"
		// Get all worlds and store them as array
		Unity::il2cppObject* s_AllWorlds = reinterpret_cast<Unity::il2cppObject*>(IL2CPP::Class::Utils::GetStaticField(WorldClass, "s_AllWorlds"));
		int itemsOffset = IL2CPP::Class::Utils::GetFieldOffset(s_AllWorlds->m_pClass, "_items");
		Unity::il2cppArray<Unity::il2cppObject*>* worldsArray = *reinterpret_cast<Unity::il2cppArray<Unity::il2cppObject*>**>(reinterpret_cast<uintptr_t>(s_AllWorlds) + itemsOffset);

		// Get the get_worldType method
		void* getWorldTypeMethod = IL2CPP::Class::Utils::GetMethodPointer(WorldClass, "get_WorldType", 0);

		// Read the specific world worldType
		for (size_t i = 0; i < worldsArray->m_uMaxLength; ++i) {
			Unity::il2cppObject* worldObject = worldsArray->At(i);

			if (worldObject == nullptr) continue;

			// Read the name of the specific world
			void* getNameMethod = IL2CPP::Class::Utils::GetMethodPointer(worldObject->m_pClass, "get_Name", 0);

			using get_Name_t = Unity::System_String* (*)(Unity::il2cppObject*);
			auto get_Name = reinterpret_cast<get_Name_t>(getNameMethod);

			Unity::System_String* nameStr = get_Name(worldObject);

			std::string worldName = nameStr->ToString();
			int32_t worldTypeValue = reinterpret_cast<int32_t(*)(Unity::il2cppObject*)>(getWorldTypeMethod)(worldObject);

			std::cout << "World Name: " << worldName << " Type: " << worldTypeValue << std::endl;

			

			void* getEntityManagerMethod = IL2CPP::Class::Utils::GetMethodPointer(worldObject->m_pClass, "get_EntityManager", 0);
			using get_EntityManager_t = Unity::CComponent(*)(Unity::il2cppObject*);
			auto get_EntityManager = reinterpret_cast<get_EntityManager_t>(getEntityManagerMethod);

			Unity::CComponent entityManager = get_EntityManager(worldObject);

And then from the World specific EntityManager I'm trying to CreateEntityQuery.

Signature is:

      "Address": 151644592,
      "Name": "Unity.Entities.EntityManager$$CreateEntityQuery",
      "Signature": "Unity_Entities_EntityQuery_o Unity_Entities_EntityManager__CreateEntityQuery (Unity_Entities_EntityManager_o __this, Unity_Entities_ComponentType_array* requiredComponents, const MethodInfo* method);",
      "TypeSignature": "iiii"
			using CreateEntityQuery_t = Unity::CComponent(*)(Unity::CComponent entityManager, Unity::il2cppArray<Unity::il2cppObject*>* componentTypes);
			auto createEntityQuery = reinterpret_cast<CreateEntityQuery_t>(createEntityQueryMethod);

			std::cout << createEntityQueryMethod << std::endl;
			// Crash is here, on call createEntityQuery
			Unity::CComponent query = createEntityQuery(entityManager, componentArray);

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions