Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Unity] Added ability to look for Classes inside the linked list of Transforms #49

Merged
merged 3 commits into from
Aug 16, 2023

Conversation

Jujstme
Copy link
Contributor

@Jujstme Jujstme commented Aug 5, 2023

This commit enhances the functionality of the SceneManager for games using the Unity engine by giving the ability to look for addresses of classes with no static reference.

Traditionally, a static entry point is deemed necessary in order to easily access a certain instance of a class / struct in Unity games. However, the use of Singletons and static references is becoming rare in modern games, as Unity devs reccommend attaching classes (especially MonoBehaviours) to a game object referenced by the currently running Unity scene.

To put it simply, each Unity scene has a linked List of game objects called Transforms, with each one having, recursively, a child Transform, and an array of Component classes, which contain the data usually needed for the autosplitting logic.

As the lack of a static reference makes it impossible to have an easy way to access those classes, the code added in this commit will provide a solution.
However, whenever possible, using a static reference shoould still be preferred, as searching through unity GameObjects is a fairly memory expensive operation (roughly 5-6 times slower).

Hierarchy and inheritance can be looked for at runtime using Micrologist's UnityInstanceDumper.

The example provided here recovers the in-game timer from the game Wretched Depths (freely available on Steam):

let scene_manager = game_engine::unity::SceneManager::wait_attach(&process).await;

loop { 
    let mut time: f32 = 0.0;

    // Accessing the main game object attached to the current scene
    if let Ok(in_game_systems) = scene_manager.get_root_game_object(&process, "InGameSystems") {
        // Accessing the child Transform named "Managers"
        if let Ok(managers) = in_game_systems.get_child(&process, &scene_manager, "Managers") {
            // Yet another child Transform with a pretty obvious name
            if let Ok(game_manager) = managers.get_child(&process, &scene_manager, "GameManager") {
                // Our class, named "GameManager", is referenced directly by the current GameObject
                if let Ok(game_manager) = game_manager.get_class(&process, &scene_manager, "GameManager") {
                    if let Ok(t_time) = process.read::<f32>(game_manager + 0x3C) {
                        time = t_time;
                    }
                }
            }
        }
    }

    timer::set_game_time(Duration::seconds_f32(time));
    next_tick().await;
}

Jujstme and others added 3 commits August 5, 2023 12:51
Probably useless in the majority of cases, but still useful in very select scenarios.
@CryZe CryZe merged commit 291c76e into LiveSplit:master Aug 16, 2023
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants