lostsmile unity mono 简单随手笔记

该话题被推 逆向工程 实用技术lostsmileunity
浏览数 - 112发布于 - 2026-01-31 - 10:41

重新编辑于 - 2026-01-31 - 10:44

前几天也发布了汉化补丁,想着是时候分享一下这个项目仓库,给大家参考一下unity的旮旯给木是怎么动态替换文件以及制作共存补丁。 汉化补丁发布原贴:https://tieba.baidu.com/p/10439551885, 仓库地址:https://github.com/cokkeijigen/lostsmile_cn/,大家感兴趣的可以到仓库去看看源码()

本项目仅供学习交流使用,严禁一切商业或特殊用途!!! Image text 

  • 游戏详细:https://vndb.org/v23409

  • LOSTSMILE_CN:程序hook相关,实现了资源重定向,可以与原版资源共存。

  • Assembly-CSharp:原版Assembly-CSharp.dll反编译源码,修复存档路径、立绘显示等若干bug,以及添加自定义AssetBundle加载和资源替换(注:release分支为未修改过的源码)。

0x00 如何打包使用Unity打包Assetbundle

首先要知道游戏的unity版本,这个可以通过在游戏主程序.exe的属性或者UnityPlayer.dll属性中查看,再或者用ida打开UnityPlayer.dll查找字符串version或者UnityPlayer等字眼找到。 Image textUnityArchive中下载对应版本的Unity,这个游戏的版本为2018.4.15f1,相信聪明的你,一定不用多说也知道怎么下载安装了吧() Image text 接着随便新建一个项目,Template随意,用默认的就行了。 Image text 来到项目Assets目录下新建一个Editor的目录,进入里面接着创建一个C#脚本,名称随意,我这里叫BuildAssetBundle,内容如下: Image text

cs
using UnityEngine;
using UnityEditor;
using System.IO;

public class BuildAssetBundles : MonoBehaviour
{
    // 向Unity右键菜单添加一个选项
    [MenuItem("Assets/Build AssetBundles")]
    static void BuildAllAssetBundles() 
    {
        // 设置AB包输出路径
        string assetBundleDirectory = Path.Combine(Application.streamingAssetsPath, "AssetBundles");
        if (!Directory.Exists(assetBundleDirectory))
        {
            Directory.CreateDirectory(assetBundleDirectory);
        }

        // 构建StandaloneWindows的AB包
        BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
    }
}

回到Assets,创建一个目录用于存档要打包的资源,名称也随意,我这里叫LostSmile,点击目录,可以看到右下角有个Asset Lables,没有可以新建一个,第一个是输出的文件名,第二个是后缀名Image text 进入LostSmile,将要打包的资源放入。 Image text 回到外面,在LostSmile右键Build AssetBundles即可。 Image text 输出的AssetBundles就在项目目录下的Assets\StreamingAssets\AssetBundlesImage text

0x01 加载自己打包的AssetBundles并替换

首先创建一个工具类,用来管理我们自己的AssetBundle:CHSPatch::AssetPatchManager

cs
public class AssetPatchManager
{

    private static readonly List<AssetBundle> AssetBundles = new List<AssetBundle>();

    static AssetPatchManager()
    {
        string cnBundlesDir = Directory.GetCurrentDirectory();
        cnBundlesDir = Path.Combine(cnBundlesDir, "LOSTSMILE_CN");
        if (Directory.Exists(cnBundlesDir))
        {
            foreach (string filePath in Directory.GetFiles(cnBundlesDir))
            {
                try
                {
                    if (filePath.EndsWith(".dll")) continue;
                    AssetBundle assetBundle = AssetBundle.LoadFromFile(filePath);
                    if (assetBundle == null) continue;
                    AssetBundles.Add(assetBundle);
                }
                catch (Exception e)
                {
                    Logger.OutMessage($"[ERRO] AssetPatchManager: {e.Message}");
                }
            }
        }
    }

    public static bool GetAssetIfExists(string fileName, out StaticAsset staticAsset)
    {
        staticAsset = null;
        //Logger.OutMessage($"查找文件:{fileName}");
        foreach (AssetBundle bundle in AssetBundles)
        {
            try
            {
                if (bundle.Contains(fileName))
                {
                    staticAsset = new StaticAsset
                    {
                        Asset = bundle.LoadAsset<UnityEngine.Object>(fileName)
                    };
                    Logger.OutMessage($"找到文件:{fileName}");
                    return staticAsset.Asset != null;
                }
            }
            catch (Exception e)
            {
                Logger.OutMessage($"[ERRO] AssetPatchManager::GetAssetIfExists: {e.Message}");
            }
        }
        return false;
    }
}

找到游戏获取AssetFile的地方插入自己写的方法调用代码,位置在: Utage::StaticAssetManager::FindAssetFile

cs
public AssetFileBase FindAssetFile(AssetFileManager mangager, AssetFileInfo fileInfo, IAssetFileSettingData settingData)
{

    if (Assets == null)
	{
		return null;
	}
	string assetName = FilePathUtil.GetFileNameWithoutExtension(fileInfo.FileName);
    // iTsukeziegn++ 
    StaticAsset staticAsset; // 尝试替换资源文件
    if (!AssetPatchManager.GetAssetIfExists(assetName.ToLower(), out staticAsset))
    {
        staticAsset = Assets.Find(x => x.Asset.name == assetName);
        if (staticAsset == null)
        {
            return null;
        }
    }
    // end
	return new StaticAssetFile(staticAsset, mangager, fileInfo, settingData);
}

0x02 修复存档中的绝对路径

Image text 为了保证存档兼容原版,我这里选择了在获取AssetFile的地方替换路径 (可能不是最佳位置,能跑就行),位置:Utage::AssetFileManager::GetFileCreateIfMissing

cs
private static string CurrentDir;

public static AssetFile GetFileCreateIfMissing(string path, IAssetFileSettingData settingData = null)
{
    if ((CurrentDir != null || (CurrentDir = Directory.GetCurrentDirectory().Replace("\\", "/")) != null) && !path.Contains(CurrentDir))
    {
        int index = path.LastIndexOf("/LOSTSMILE_Data");
        path = ((index != -1) ? ("file:///" + CurrentDir + path.Substring(index)) : path);
    }
    if (!IsEditorErrorCheck)
    {
        return GetInstance().AddSub(path, settingData);
    }
    if (path.Contains(" "))
    {
        Debug.LogWarning("[" + path + "] contains white space");
    }
    return null;
}

0x03 修复翻译角色名字后部分立绘不显示

Image text 手动改的地方太多了,避免产生新的bug,因此这里采用动态替换,完整代码:Utage::AdvCharacterInfo

cs
public class AdvCharacterInfo
{
    public static AdvCharacterInfo Create(AdvCommand command, AdvSettingDataManager dataManager)
    {
        // ...其他代码

        // 对话角色名字文本
        string text = command.ParseCell<string>(AdvColumnName.Arg1);
        // 获取原文角色名字
        string characterLabel = GetRawCharacterName(text);  

        // ...其他代码
    }

    private static string GetRawCharacterName(string text)
	{
		return text switch
		{
			"海洋之神" => "沖ツ御神",
			"棉花糖" => "わたあめ",
			"由希子" => "由希子",
			"美铃" => "美鈴",
			"春纪" => "春紀",
			// ...此处省略
			_ => text,
		};
	}
}

其他修改的地方可以到Assembly-CSharp搜索注释iTsukezigen++查看()

0x04 如何编译

Assembly-CSharp.dll(由ILSpy反编译生成的vs项目)

用vs打开项目,首先是补全依赖,编辑Assembly-CSharp.csproj中的 "GamePath",替换成你的游戏安装路径。接着Ctrl + B编译即可。

xml
<PropertyGroup>
    <GamePath>I:\Galgame\lostsmile</GamePath>
    <AssemblyName>Assembly-CSharp</AssemblyName>
    <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
    <TargetFramework>net4.7</TargetFramework>
</PropertyGroup>

Image text 或者使用命令行

cmd
cd Assembly-CSharp
dotnet build .\Assembly-CSharp.sln -p:WarningLevel=0 --configuration Release

LOSTSMILE_CN.exeLOSTSMILE_CN.dll

  • 安装VC-LTL5,可以不安装,但是编译出来的文件体积可能会有点大。

  • vs打开等待cmake缓存完成,接着Ctrl + B编译即可。或者直接运行build.bat

Image text

本文版权遵循 CC BY-NC 协议 本站版权政策

(。>︿<。) 已经一滴回复都不剩了哦~