Skip to content

nomnomab/unity-project-patcher

Repository files navigation

Unity Project Patcher

A tool that generates a Unity project from a game build that can be playable in-editor


Table of Contents

About the Project

This tool takes a unity game, extracts its assets/scripts/etc, and then generates a project for usage in the Unity editor.

Important

Only supports Mono games at the moment!

This tool does not distribute game files. It simply works off of your copy of the game!

Also, this tool is for personal use only. Do not re-distrubute game files to others.

This core tool doesn't patch any game by itself itself, as it's just a core utility. Game wrappers have to utilize this core to set up its pipeline, and any specific fixing for that specific game.

Note

I will not be taking requests for game wrappers to make 👍

Features

  • Custom tool window content
  • Auto-detected game wrappers for tool window usage
  • A rough package detector
  • A unity version detector
  • A unity SRP pipeline detector
  • Configurable Asset Ripper settings in the editor via a ScriptableObject
  • Basic folder mappings
  • Many provided patcher steps for common use-cases
  • Script decompilation via Asset Ripper
  • NGO code gen removal
  • Much more

Getting Started

Already Bundled

This project is bundled with the following packages:

Gets Downloaded

This project downloads a slightly tweaked version of Asset Ripper, and is downloded from the releases of my fork here.

Note

This is only downloaded if it is missing locally from [PROJECT_NAME]\AssetRipper

Prerequisites

You will have to make sure you have the following before using the tool in any way:

Installation

Important

These options require git to be installed!

Core package

Install with the package manager:

  1. Open the Package Manager from Window > Package Manager
  2. Click the '+' button in the top-left of the window
  3. Click 'Add package from git URL'
  4. Provide the URL of the this git repository: https://github.com/nomnomab/unity-project-patcher.git
    • If you are using a specific version, you can append it to the end of the git URL, such as #v1.2.3
  5. Click the 'add' button

Install with the manifest.json:

  1. Open the manifest at [PROJECT_NAME]\Packages\manifest.json
  2. Insert the following as an entry:
"com.nomnom.unity-project-patcher": "https://github.com/nomnomab/unity-project-patcher.git"
  • If you are using a specific version, you can append it to the end of the git URL, such as #v1.2.3

BepInEx

This can be installed via the tool window in-editor if a package depends on it.

If you require BepInEx usage, then follow the instructions at https://github.com/nomnomab/unity-project-patcher-bepinex

Usage

The tool window can be opened via Tools > Unity Project Patcher > Open Window

Important

This tool mostly supports patching an already patched project, although this can lead to broken assets. So make sure you back up your project beforehand.

When pressing the patch button, it may prompt you to fix various paths in your UPPatcherUserSettings asset.

Available configs can be accessed via Tools > Unity Project Patcher > Configs

Patcher Configs

UPPatcherUserSettings

This config is for defining the user's Asset Ripper download path, export path, and game install folder.

If this isn't made manually, when the tool is ran it will make one and direct the user to it before starting.

Note

The end user won't have to touch these, only the game wrapper creator!

Any game wrapper will require the following two ScriptableObjects:

UPPatcherSettings

Note

Can be made via Create > Unity Project Patcher > Settings

One will be made for you in the project root, upon opening the tool, if one doesn't exist.

This can be retrieved in a custom step via this.GetSettings();.

This is the core settings object. Here is where you define where the game is, can click the Get buttons to get the name, version, and pipeline type for the game, and can define various other options relating to the way the patcher will use files.

Dlls To Copy

These DLLs will be copied from the game's Managed folder, provided with a relative path.

The output path defines where the dll will end up relative to the Plugins folder defined in your AssetRipperSettings

  • This path is relative, so an empty path will equate to just the Plugins folder.

Script Dll Folders to Copy

Not all plugins can be copied over as just dlls. Some might need editing of scriptable objects, or other types, so this lets you define which folders in the Asset Ripper export Scripts folder will be copied directly into the project.

Ignored Dll Prefixes

We can ignore certain packages that have a specific prefix with this

Packages helper

At the bottom of this asset are field for packages, and a button called GetGamePackages that lets you find possible packages for the game's version, that match the current editor's version.

Important

This should be used in a project that is the same version as the game's Unity version! Otherwise it will lead to incompatible package versions.

Note, the package process will be a slight headache to figure out as this tool is just an assumption helper.

To figure out packages slightly faster, you can run the tool until it throws an error when the scripts are imported, then you can work backwards from there with the errors.

Exact Packages Found

These packages are most likely in the game, but can be incorrect.

Possible Packages Found

These packages might be relevant to the game, but can be incorrect.

Improbable Packages Found

These packages are most likely not relevant to the game, but can be incorrect.

Git Packages

If you need to put any git packages in the wrapper, put them here.

AssetRipperSettings

Note

Can be made via Create > Unity Project Patcher > AssetRipper Settings

One will be made for you in the project root, upon opening the tool, if one doesn't exist.

This can be retrieved in a custom step via this.GetAssetRipperSettings();.

Folder Mappings

Each folder mapping is a key/value pair that lets you map an export folder to a new project folder location.

An example can be:

  • Key: MonoBehaviour
    • Used to fetch the output path, has to be unique
  • SourceName: MonoBehaviour
    • In the export this maps to AssetRipperOutput\ExportedProject\Assets\MonoBehaviour
  • OutputPath: ScriptableObjects
    • In the project this maps to Assets\[GAME_NAME]\Game\ScriptableObjects

This is very useful to make the project structure easier to work with!

Folders to Copy

Just because there is a folder mapping, doesn't mean the folder will be copied into the project!

Here you put folder names for folders in the export that you want to copy directly into the project.

Such as:

  • MonoBehaviour
  • Scripts\Assembly-CSharp

Folders to Exclude from Copy

Not all folders in the above folders will need to be copied, so you can define exclusions here.

Folders to Exclude from Read

These folders are completely excluded from asset scrubbing to make reading faster.

Project Settings to Copy

These copy various project settings from the exports AssetRipperOutput\ExportedProject\ProjectSettings folder

Configuration Data

This is essentially your Asset Ripper configuration data that Asset Ripper will read.

Warning

Not all settings are applicable to the free version of Asset Ripper, as some are paid features.

This includes settings like:

  • Static Mesh Separation
  • Asset De-duplication

If you set the script export mode to anything other than Decompiled, it will skip code-specific steps in the patcher.

This can easily be checked in custom steps with this.ScriptsAreStubs(); which can be used in an IPatcherStep or manually via PatcherUtility.ScriptsAreStubs().

Custom Game Wrapper

Preresiquites

  • Generate a local unity package
  • Add the following to your game's package Assembly Definition References in the inspector:
    • com.nomnom.unity-project-patcher.Editor.asmdef
    • com.nomnom.unity-project-patcher.Runtime.asmdef
    • UniTask.asmdef

Creation

Games require a custom game wrapper to work in the first place, as this tool is just a core tool.

This is very simple however:

[UPPatcher]
public static class MyGameWrapper {
    // gives you the pipeline so you can modify its execution steps
    public static void GetSteps(StepPipeline stepPipeline) {
        stepPipeline.SetInputSystem(InputSystemType.InputSystem_New);
        stepPipeline.IsUsingAddressables();
        stepPipeline.IsUsingNetcodeForGameObjects();
        stepPipeline.InsertAfter<InjectHDRPAssetsStep>(
            new ChangeSceneListStep("MyCustomSceneIsFirst")
        );
        stepPipeline.SetGameViewResolution("16:9");
        stepPipeline.OpenSceneAtEnd("OpenThisSceneLast");
    }
}

The tool window at Tools > Unity Project Patcher > Open Window will automatically locate the first game wrapper it finds, and will work off of it when pressing the Run Patcher button.

You can find all available internal steps in the Nomnom.UnityProjectPatcher.Editor.Steps namespace.

If a step recompiles or restarts the editor, it will tell you in its type summary.

Important

Steps are unique and as such cannot be in the pipeline more than once!

A custom step

public readonly struct RestartEditorStep: IPatcherStep {
    // runs when its this step's turn
    // add async to await operations when needed
    public UniTask<StepResult> Run() {
        return UniTask.FromResult(StepResult.Success);
    }
    
    // runs when the executor succeeds or fails
    public void OnComplete(bool failed) { }
}

The default pipeline steps

public readonly List<IPatcherStep> Steps = new List<IPatcherStep>() {
    new GenerateDefaultProjectStructureStep(),
    new ImportTextMeshProStep(),
    new GenerateGitIgnoreStep(),
    new GenerateReadmeStep(),
    new PackagesInstallerStep(), // recompile
    new CacheProjectCatalogueStep(),
    new AssetRipperStep(),
    new CopyGamePluginsStep(), // recompile
    new CopyExplicitScriptFolderStep(), // restarts
    new EnableUnsafeCodeStep(), // recompiles
    new CopyProjectSettingsStep(allowUnsafeCode: true), // restart
    new GuidRemapperStep(),
    new CopyAssetRipperExportToProjectStep(), // restarts
    new FixProjectFileIdsStep(),
    new SortAssetTypesSteps()
};

If URP or HDRP is defined in the UPPatcherSettings asset, then it will automatically inject the step for it.

The StepPipeline defines insertion functions, as well as pre-defined functions that will insert steps at specific locations for you, such as pipeline.IsUsingNetcodeForGameObjects(), which will insert the needed step to handle NGO scripts for you.

Note

You can check the final pipeline steps via the patcher window at Tools > Unity Project Patcher > Open Window, and clicking on the Print Steps to Log button! The steps will be put into unity's console.

For HDRP

There is InjectHDRPAssetsStep which will inject the various settings files into the project/quality settings for you.

For URP

There is InjectURPAssetsStep which will inject the various settings files into the project/quality settings for you.

Publishing

Then when you put your game wrapper in a GitHub repository, make sure you include instructions on installing this package first, as git packages cannot have other git dependencies.

Also, make sure you bundle the UPPatcherSettings and AssetRipperSettings ScriptableObjects into your package inside of its Runtime folder. This will let them be bundled for the user!

FAQ

Q: An asset's values got messed up, can I reset it?

As long as you have the Asset Ripper export still, haven't touched it, and the asset's fileids/guids haven't changed, then yes you can.

Right-click the asset in the project, then select Assets > Experimental > Re-import from Export.

Warning

Does not support re-importing scenes or prefabs at the moment.

Q: How do I migrate my current project to this one?

Note

This does not modify any of your original project's files!

  1. Run patcher to generate new project
  2. Wait for that to finish
  3. Import patcher into original project
  4. Tools > Unity Project Patcher > Other > Scrub > Project
  5. Wait for that to finish
  6. In new patched project
  7. Tools > Unity Project Patcher > Other > Import Assets from Another Project
  8. For the first file prompt, select [Original project name]/Assets/scrub.project.txt.json
  9. For the second folder prompt, select the root folder for your mod that has all of its assets inside of it
    • Do not select /Assets/
    • Make a folder, such as /Assets/MyCoolMod, and put everything the mod needs into it
    • If you rely on external mods, include the entire mod, not just the dll as many require asset bundles!
    • The name of this folder is what the name of the output folder will be
  10. Wait for that to finish
  11. Your old project contents will now be in /Assets/[Game Name]/Mods/plugins
  12. Done

Q: How do I add assets after patching to the current project?

Ok so this is done in two ways:

  1. If the assets are not already included in the base game
    1. Simply copy them into the project 👍

Note

There is a bug with this step!

If another asset or something in the game has the same type + name as something in the incoming files, then it will falsely think it is already in the project.

Verify your files are correct after it finishes!

  1. If the assets are in the base game
    1. Make a new unity project
    2. Make a folder to put all of the new assets into
    3. Tools > Unity Project Patcher > Other > Scrub > Project
    4. Wait for that to finish
    5. In new patched project
    6. Tools > Unity Project Patcher > Other > Replace Assets with Assets from Another Project
    7. For the first file prompt, select [Original project name]/Assets/scrub.project.txt.json
    8. For the second folder prompt, select the root folder for your mod that has all of its assets inside of it
      • From step 2
      • Do not select /Assets/
      • Make a folder, such as /Assets/MyFolder, and put everything you want to import into it
    9. For the third folder prompt, select a folder in the patched project to act as the "Files not already in this project" folder
      • Do not select anything inside of /Assets/[Game Name]/Game
    10. Wait for that to finish
    11. Done

Games I Tested With

  • Lethal Company
  • Content Warning
    • Not fully, as Photon is being confusing
  • ULTRAKILL
  • Cult of the Lamb
    • Asset Ripper bug is preventing this one

ko-fi

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages