内容将会持续更新,有错误的地方欢迎指正,谢谢!
拥有更好的学习体验 —— 不断努力,不断进步,不断探索 |
助力快速掌握 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" -
跨平台方案:
# Mac用户通过Homebrew安装 brew install subversion # Linux用户 sudo apt-get install subversion
2、将SVN工具集成到Unity项目
安装完成后,将SlickSVN的安装目录中的bin文件夹内容拷贝到Unity项目的Plugins文件夹中。确保包含svn.exe及相关支持文件。
原理:将svn.exe及其依赖文件放入项目目录中,可以在Unity中直接调用这些工具,避免了环境变量配置的麻烦。
💡 注意:通过条件编译指令实现跨平台兼容
#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工具类
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命令
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列表
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文件内容
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目录
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工具类调用
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地址也需要保证存在,否则会导致操作失败。
每一次跌倒都是一次成长 每一次努力都是一次进步 |
如果您喜欢本博客,请点赞和分享给更多的朋友,让更多人受益。同时,您也可以关注我的博客,以便及时获取最新的更新和文章。
在未来的写作中,我将继续努力,分享更多有趣、实用的内容。再次感谢大家的支持和鼓励,期待与您在下一篇博客再见!