Unity与SVN集成:实现高效版本控制

内容将会持续更新,有错误的地方欢迎指正,谢谢!

Unity与SVN集成:实现高效版本控制


|-----------------------------------------------------|
| TechX 坚持将创新的科技带给世界! 拥有更好的学习体验 ------ 不断努力,不断进步,不断探索 |

|-----------------------------------------------------------------|
| TechX ------ 心探索、心进取! 助力快速掌握 Unity与SVN集成 学习 为初学者节省宝贵的学习时间,避免困惑! |

前言:

在游戏开发过程中,版本控制是确保团队协作顺利进行的关键。Subversion(简称SVN)作为一种广泛使用的版本控制系统,在Unity项目中也得到了广泛应用。然而,如何高效地在Unity中与SVN进行交互却是一个挑战。本文将介绍如何在Unity中直接和SVN进行交互,实现一些你想要的操作。


文章目录


一、环境准备:搭建SVN桥梁

SlickSvn为 Windows 提供了一个独立的命令行 Subversion 客户端。SlickSvn在 Windows 中使用原始的 Subversion 命令行语法来操作SVN。

Unity和Svn能够交互的原理就是直接调用SlickSvn的命令行工具来和Svn进行交互。

1、安装SlickSVN命令行工具

  • Windows平台推荐方案:

    访问SlikSVN官网下载页面

    选择最新稳定版(当前推荐1.14.5)

    双击安装文件,注意勾选"Add svn to system PATH"

  • 跨平台方案:

    bash 复制代码
    # Mac用户通过Homebrew安装
    brew install subversion
    
    # Linux用户
    sudo apt-get install subversion

2、将SVN工具集成到Unity项目

安装完成后,将SlickSVN的安装目录中的bin文件夹内容拷贝到Unity项目的Plugins文件夹中。确保包含svn.exe及相关支持文件。

原理:将svn.exe及其依赖文件放入项目目录中,可以在Unity中直接调用这些工具,避免了环境变量配置的麻烦。

💡 注意:通过条件编译指令实现跨平台兼容

csharp 复制代码
#if UNITY_EDITOR_WIN
private const string SVN_EXE_NAME = "svn.exe";
#elif UNITY_EDITOR_OSX
private const string SVN_EXE_NAME = "svn";
#endif

二、实现自动化SVN交互

以下代码实现了Unity与SVN的交互功能,包括执行SVN命令、获取SVN列表、读取文件内容以及检出目录。

1、 SVNHelper工具类

csharp 复制代码
public class SVNHelper
{
    public string username; // SVN用户名
    public string password; // SVN密码
    public string svnPath;  // svn.exe的路径

    // 构造函数,初始化用户名和密码
    public SVNHelper(string username, string password)
    {
        this.username = username;
        this.password = password;

        svnPath = GetSvnClientPath(); // 获取svn.exe的路径
    }
    
    // 获取svn.exe的路径
    private string GetSvnClientPath()
    {
        var assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
        var pInfo = UnityEditor.PackageManager.PackageInfo.FindForAssembly(assembly); // 获取包信息
        if (pInfo == null)
            return null;
        var assetPath = Path.GetFullPath(pInfo.assetPath); // 获取Unity项目资源路径
        assetPath = assetPath.Replace('\\', '/'); // 统一路径格式
        var snvPath = Path.Combine(assetPath, "Plugins/SVNClient/Windows/svn.exe"); // 拼接svn.exe路径
        return snvPath;
    }
}

SVNHelper类封装了与SVN交互的核心功能,包括路径获取和命令行调用。
注意事项:如果svn.exe未找到,GetSvnClientPath方法会返回null,需要确保路径配置正确。

2、 执行SVN命令

csharp 复制代码
public async Task<string> ExecuteSVNCommandAsync(string args, string workingDir = null, CancellationToken ct = default)
{
    var commandArgs = new List<string>();

    // 添加用户名和密码参数
    if (!string.IsNullOrEmpty(username))
        commandArgs.Add($"--username \"{username}\"");

    if (!string.IsNullOrEmpty(password))
        commandArgs.Add($"--password \"{password}\" --non-interactive");

    commandArgs.Add(args);

    // 检测svn.exe是否存在
    if (!File.Exists(svnPath))
        throw new FileNotFoundException($"SVN client not found at: {svnPath}");

    // 配置进程启动信息
    var startInfo = new ProcessStartInfo
    {
        FileName = svnPath,
        Arguments = string.Join(" ", commandArgs),
        UseShellExecute = false,
        RedirectStandardOutput = true,
        RedirectStandardError = true,
        CreateNoWindow = true,
        WorkingDirectory = workingDir ?? Application.dataPath // 默认使用Unity项目的Assets目录
    };

    var output = new StringBuilder();
    var errorOutput = new StringBuilder();

    // 启动进程并读取输出
    using (var process = new Process { StartInfo = startInfo })
    {
        process.Start();
        using (var outputReader = process.StandardOutput)
        using (var errorReader = process.StandardError)
        {
            string outputText = await outputReader.ReadToEndAsync();
            string errorText = await errorReader.ReadToEndAsync();

            output.Append(outputText);
            errorOutput.Append(errorText);
        }

        // 等待进程结束
        await WaitForExitAsync(ct);

        // 检查退出码
        if (process.ExitCode != 0)
        {
            throw new InvalidOperationException(
                $"SVN command failed with code {process.ExitCode}. Error: {errorOutput}"
            );
        }

        return output.ToString().Trim();
    }
}

public Task WaitForExitAsync(Process process, CancellationToken ct = default)
{
    var tcs = new TaskCompletionSource<bool>();
    process.EnableRaisingEvents = true;
    process.Exited += (sender, args) => tcs.TrySetResult(true);// 进程结束时触发
    ct.Register(() => tcs.TrySetCanceled());// 处理取消请求
    return tcs.Task;
}

ExecuteSVNCommandAsync方法封装了SVN命令的执行过程,支持异步操作和错误处理。
通过ProcessStartInfo启动svn.exe进程,并读取其标准输出和错误输出。
注意事项:确保用户名和密码正确,否则可能导致命令执行失败。

3、 获取SVN列表

csharp 复制代码
public async Task<List<string>> GetSVNListAsync(string svnUrl, CancellationToken ct = default)
{
    try
    {
        // 使用svn list命令递归列出所有文件和文件夹
        string output = await ExecuteSVNCommandAsync($"list \"{svnUrl}\" --depth infinity", ct: ct);
        var entries = output.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
        entries = entries.Select(item => item.Trim()).ToArray();

        // 过滤出包含package.json的文件夹路径
        var packages = new HashSet<string>();
        foreach (var entry in entries)
        {
            if (ct.IsCancellationRequested)
                break;

            if (entry.EndsWith("package.json", StringComparison.OrdinalIgnoreCase))
            {
                string packageUrl = entry.Substring(0, entry.Length - "package.json".Length).TrimEnd('/');
                string packageSvnUrl = $"{svnUrl}/{packageUrl}";
                packages.Add(packageSvnUrl);
            }
        }

        return packages.ToList();
    }
    catch (Exception ex)
    {
        UnityEngine.Debug.LogError($"获取包列表失败: {ex.Message}");
        throw;
    }
}

GetSVNListAsync方法递归列出SVN仓库中的文件和文件夹,并过滤出包含package.json的路径。
通过svn list --depth infinity命令获取所有条目,并通过字符串处理筛选目标路径。
注意事项:递归列出的性能可能较低,适用于小型仓库。

4、 获取SVN文件内容

csharp 复制代码
public async Task GetSVNFileContentAsync(string packageUrl, string fileName, CancellationToken ct = default)
{
    string svnUrl = $"{packageUrl}/{fileName}";
    string content = await ExecuteSVNCommandAsync($"cat \"{svnUrl}\"", ct: ct); // 使用svn cat命令获取文件内容
    return content ;
}

GetSVNFileContentAsync方法从SVN仓库中读取文件内容并反序列化为指定类型。
通过svn cat命令获取文件内容,并使用JsonConvert.DeserializeObject进行反序列化。
注意事项:确保文件内容和目标类型匹配,否则可能导致反序列化失败。

5、 检出SVN目录

csharp 复制代码
public async Task CheckoutFolderAsync(string packageUrl, string localPath, CancellationToken ct = default)
{
    if (string.IsNullOrEmpty(packageUrl))
        throw new ArgumentException("package Url cannot be empty.");

    if (string.IsNullOrEmpty(localPath))
        throw new ArgumentException("Local path cannot be empty.");

    string svnUrl = $"{packageUrl}";
    string args = $"checkout \"{svnUrl}\" \"{localPath}\"";

    try
    {
        await ExecuteSVNCommandAsync(args, Path.GetDirectoryName(localPath), ct); // 执行svn checkout命令
    }
    catch (Exception ex)
    {
        UnityEngine.Debug.LogError($"检出失败: {ex.Message}");
        throw;
    }
}

CheckoutFolderAsync方法从SVN仓库中检出指定目录到本地路径。
通过svn checkout命令实现目录检出。
注意事项:确保本地路径可写,否则可能导致检出失败。


三、SVNHelper工具类调用

csharp 复制代码
public class SVNInteraction : MonoBehaviour
{
    public string username;
    public string password;
    public string svnUrl;

    public string checkoutPath;

    public SVNHelper svnHelper;

    // Start is called before the first frame update
    async void Start()
    {
        svnHelper = new SVNHelper(username, password);

        List<string> packageUrls = await svnHelper.GetSVNListAsync(svnUrl);

        string content = await svnHelper.GetSVNFileContentAsync(svnUrl,"package.json");

        await svnHelper.CheckoutFolderAsync(svnUrl, checkoutPath);
    }
}

请确保账号密码的正确性,否则会导致验证失败,svn地址也需要保证存在,否则会导致操作失败。


|-----------------------------------------------|
| TechX ------ 心探索、心进取! 每一次跌倒都是一次成长 每一次努力都是一次进步 |


END 感谢您阅读本篇博客!希望这篇内容对您有所帮助。如果您有任何问题或意见,或者想要了解更多关于本主题的信息,欢迎在评论区留言与我交流。我会非常乐意与大家讨论和分享更多有趣的内容。
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!

相关推荐
Irene19915 小时前
SVN 报错 Previous operation has not finished,提示需要 clean up
svn
真鬼12317 小时前
【Unity 6】Unity6快捷下载,快速下载
unity·游戏引擎
会潜水的小火龙18 小时前
unity打包apk报错Failure to initialize问题解决方法
unity·游戏引擎
平行云20 小时前
实时云渲染平台数据通道,支持3D应用文件上传下载分享无缝交互
linux·unity·云原生·ue5·gpu算力·实时云渲染·像素流送
Sator11 天前
unity仅用粒子系统实现拖尾
unity·游戏引擎
游乐码1 天前
Unity基础(五)四元数相关
unity·游戏引擎
想做后端的前端1 天前
Unity热更新 - HybridCLR & YooAsset
unity·游戏引擎
鹿野素材屋1 天前
Unity预加载:减少游戏中首次加载资源时的卡顿
windows·游戏·unity
RPGMZ1 天前
RPGMZ游戏引擎事件技巧大全
javascript·游戏引擎·事件·rpgmz·rpgmakermz
天若有情6731 天前
Superpowers 游戏引擎核心应用场景与落地指南
游戏引擎·superpowers