asr::game_engine

Module unity

Source
Available on crate feature unity only.
Expand description

Support for games using the Unity engine.

§Example

use asr::{
    future::retry,
    game_engine::unity::il2cpp::{Module, Version},
    Address, Address64,
};

// We first attach to the Mono module. Here we know that the game is using IL2CPP 2020.
let module = Module::wait_attach(&process, Version::V2020).await;
// We access the .NET DLL that the game code is in.
let image = module.wait_get_default_image(&process).await;

// We access a class called "Timer" in that DLL.
let timer_class = image.wait_get_class(&process, &module, "Timer").await;
// We access a static field called "_instance" representing the singleton
// instance of the class.
let instance = timer_class.wait_get_static_instance(&process, &module, "_instance").await;

// Once we have the address of the instance, we want to access one of its
// fields, so we get the offset of the "currentTime" field.
let current_time_offset = timer_class.wait_get_field_offset(&process, &module, "currentTime").await;

// Now we can add it to the address of the instance and read the current time.
if let Ok(current_time) = process.read::<f32>(instance + current_time_offset) {
   // Use the current time.
}

Alternatively you can use the Class derive macro to generate the bindings for you. This allows reading the contents of an instance of the class described by the struct from a process. Each field must match the name of the field in the class exactly (or alternatively renamed with the #[rename = "..."] attribute) and needs to be of a type that can be read from a process. Fields can be marked as static with the #[static_field] attribute.

#[derive(Class)]
struct Timer {
    #[rename = "currentLevelTime"]
    level_time: f32,
    #[static_field]
    foo: bool,
}

This will bind to a .NET class of the following shape:

class Timer
{
    float currentLevelTime;
    static bool foo;
    // ...
}

The class can then be bound to the process like so:

let timer_class = Timer::bind(&process, &module, &image).await;

Once you have an instance, you can read the instance from the process like so:

if let Ok(timer) = timer_class.read(&process, timer_instance) {
    // Do something with the instance.
}

If only static fields are present, the read method does not take an instance argument.

Modules§

il2cpp
Support for attaching to Unity games that are using the IL2CPP backend.
mono
Support for attaching to Unity games that are using the standard Mono backend.

Structs§

Scene
A scene loaded in the attached game.
SceneManager
The scene manager allows you to easily identify the current scene loaded in the attached Unity game.
Transform
A Transform is a base class for all entities used in a Unity scene. All classes of interest useful for an auto splitter can be found starting from the addresses of the root Transforms linked in each scene.

Functions§

get_scene_name
Returns the name of the scene from the given scene path. This path is usually retrieved from SceneManager::get_current_scene_path.