UnityResolve.hpp Documentation

repository·main·Indexed 19 days ago

https://github.com/issuimo/unityresolve.hpp

A C++ library for interacting with Unity game engines (Mono and Il2cpp) at runtime. It enables native code to manipulate managed C# objects, fields, and methods across Windows, Android, Linux, iOS, and HarmonyOS. Features include Mono assembly injection, C# GC thread management, instantiation of managed types, and tools for finding Unity objects and components.

Tokens
1.7K
Snippets
9
Records
9
Agent score
16%

What's inside unityresolve.hpp

  1. Configure UnityResolve.hpp build settings

    main

    Before including the header, you must define your target platform and optional dependencies using preprocessor macros.

    • GLM Support: Define USE_GLM to use the GLM library for math types.
    • Platform Selection: Define exactly one platform macro (e.g., WINDOWS_MODE, ANDROID_MODE, LINUX_MODE) to set the target environment.
    #define USE_GLM
    #define WINDOWS_MODE 1
    #define ANDROID_MODE 0
    #define LINUX_MODE 0
    
    #include "UnityResolve.hpp"
  2. Create C# strings, arrays, and objects

    main

    You can instantiate managed C# types from native code:

    • Strings: Use UnityResolve::UnityType::String::New("content").
    • Arrays: Use UnityResolve::UnityType::Array<T>::New(pClass, size).
    • Objects: Use pClass->New<T*>() to create a new instance of a class.
    // Create String
    const auto str = UnityResolve::UnityType::String::New("hello");
    std::string cppStr = str.ToString();
    
    // Create Array
    const auto array = UnityResolve::UnityType::Array<int>::New(pClass, 10);
    std::vector<int> cppVector = array.ToVector();
    
    // Create Object Instance
    const auto pGame = pClass->New<Game*>();
  3. Initialize UnityResolve

    main

    Initialize the library by providing the handle to the game's engine module (GameAssembly.dll or mono.dll for Il2cpp, or mono.dll for Mono) and specifying the usage mode.

    Modes:

    • UnityResolve::Mode::Mono
    • UnityResolve::Mode::Il2cpp
    // Windows (Mono/Il2cpp)
    UnityResolve::Init(GetModuleHandle(L"GameAssembly.dll | mono.dll"), UnityResolve::Mode::Mono);
    
    // Linux or Android
    UnityResolve::Init(dlopen(L"GameAssembly.so | mono.so", RTLD_NOW), UnityResolve::Mode::Mono);
  4. Access and invoke C# fields and methods

    main

    UnityResolve allows you to traverse the assembly hierarchy to find classes, access fields (get/set), and invoke methods.

    Workflow:

    1. Get the assembly using UnityResolve::Get("assembly.dll").
    2. Get the class using assembly->Get("ClassName").
    3. Access fields via pClass->Get<UnityResolve::Field>("FieldName") or pClass->Get<T>("FieldName") for offsets.
    4. Access methods via pClass->Get<UnityResolve::Method>("MethodName").
    5. Use Invoke<T>(args...) or Cast<T>(...) to execute methods.
    const auto assembly = UnityResolve::Get("assembly.dll");
    const auto pClass   = assembly->Get("className");
    
    // Field Access
    const auto field = pClass->Get<UnityResolve::Field>("FieldName");
    int val = pClass->GetValue<int>(objInstance, "fieldName");
    pClass->SetValue<int>(objInstance, "fieldName", 123);
    
    // Method Invocation
    const auto method = pClass->Get<UnityResolve::Method>("MethodName");
    method->Invoke<int>(114, 514, "arg_string");
    
    // Method Casting (for direct calls)
    const UnityResolve::MethodPointer<void, int, bool> ptr = method->Cast<void, int, bool>();
    ptr(114514, true);
  5. Attach and Detach C# GC threads

    main

    Use these methods to manage thread attachment for the C# Garbage Collector (GC) to ensure stability when interacting with managed objects from native threads.

    // C# GC Attach
    UnityResolve::ThreadAttach();
    
    // C# GC Detach
    UnityResolve::ThreadDetach();
  6. Convert between World and Screen coordinates

    main

    Use the Camera type to perform coordinate transformations. You must first obtain the main camera instance.

    Camera* pCamera = UnityResolve::UnityType::Camera::GetMain();
    Vector3 screenPoint = pCamera->WorldToScreenPoint(worldPos, Eye::Left);
    Vector3 worldPos    = pCamera->ScreenToWorldPoint(screenPoint, Eye::Left);
  7. Find Unity objects and components

    main

    Locate existing instances in the Unity engine:

    • Find Objects by Type: Use pClass->FindObjectsByType<T*>() to get a list of all active instances of a class.
    • Get Components: Use gameobj->GetComponents<T*>(classPtr), GetComponentsInChildren<T*>(classPtr), or GetComponentsInParent<T*>(classPtr) to retrieve components from a GameObject.
    // Find all instances of a class
    const auto assembly = UnityResolve::Get("assembly.dll");
    const auto pClass   = assembly->Get("PlayerClass");
    std::vector<Player*> players = pClass->FindObjectsByType<Player*>();
    
    // Get components from a GameObject
    std::vector<T*> components = gameobj->GetComponents<T*>(assembly->Get("ComponentClass"));
  8. Inject a Mono Assembly

    main

    Load a C# assembly into the running process. You can provide a simple path or specify the assembly name, class, and method to invoke for initialization.

    // Simple load
    UnityResolve::AssemblyLoad assembly("./MonoCsharp.dll");
    
    // Load with specific entry point: AssemblyName, ClassName, MethodName, FullMethodPath
    UnityResolve::AssemblyLoad assembly("./MonoCsharp.dll", "MonoCsharp", "Inject", "MonoCsharp.Inject:Load()");