Unity构建详解(12)——自动构建

【前言】

自动构建是指整个构建流程不需要人工操作,只需要输入启动构建指令即可获取构建结果。实现这样的自动构建需要满足以下条件:

  • 支持命令行参数启动
    • 我们不可能每次构建时都打开Unity去手动点击构建,必须支持通过命令行启动Unity自动执行构建
    • 我们每次构建的需求不同,可能构建Debug、Release或者其他特殊需求的应用,因此Unity需要支持识别命令行输入的不同参数
  • 支持工程自动检查
    • 我们构建时需要保证不会出现错误,否则中途就构建失败了。错误主要来自于代码和资源,需要在其被提交到主干时就进行自动检查,而不是留在构建时出现构建失败才发现某处代码或资源不对,这是提高构建效率的措施
    • 自动检查可以提前发现潜在并帮助解决潜在的问题,减少问题影响域,使得进入游戏包体的问题减少,进而降低人力成本
  • 支持应用程序自动构建
    • 在Unity中主要是支持iOS自动构建,有两步,一是自动修改xcode工程,二是xcode工程自动执行构建
  • 支持构建结果自动上传

【命令行参数启动程序】

我们通常通过点击程序的快捷方式启动程序,而所有程序都可能通过命令行来启动,两者都是调用更底层提供的接口,就好像我们写代码提供一个接口供上层在不同地方调用一样。

以win平台为例,输入exe文件的路径,即可启动程序,例如启动QQ:"C:\Program Files\Tencent\QQ\bin\QQ.exe"。

我们知道main函数是程序的入口,会接受参数输入,我们可以在命令行中输入参数,输入的参数被传递给main函数的args,程序应该读取这些参数并做相应的处理。参数具体是什么由应用程序来定。

命令行输入参数的语法为: -参数名 参数值

不同参数之前没有先后顺序。

Unity提供了命令行参数说明,常用的如下:

  • 启动工程
    • Unity程序路径 -projectPath Unity工程路径
  • 启动工程后执行某个函数
    • Unity程序路径 -projectPath Unity工程路径 -executeMethod <NamespaceName.ClassName.MethodName>
    • 该函数必须是静态函数且位于Editor文件夹中
  • 输出log
    • Unity程序路径 -projectPath Unity工程路径 -logfile 输出文件路径
  • 执行完命令自动退出
    • Unity程序路径 -projectPath Unity工程路径 -quit
  • 不打开Unity界面执行
    • Unity程序路径 -projectPath Unity工程路径 -batchmode
  • 执行时不使用GPU
    • Unity程序路径 -projectPath Unity工程路径 -nographics
  • 设置构建的目标平台
    • -buildTarget ios
    • -buildTarget android
  • 使用CacheServer
    • -EnableCacheServer
  • 设置CacheServer端口
    • -cacheServerEndpoint 127.0.0.1:10080
  • 设置使用的图形API
    • -force-gles
    • -force-vulkan
    • -force-d3d12

更进一步的,我们不可能每次都手动在命令行输入一堆东西,我们需要像点击快捷方式一样,直接运行这些指令,这时就用到bat脚本。bat脚本可以直接问ChatGPT。

@echo off
cd "Unity安装目录路径"
Unity.exe -projectPath "项目路径" -executeMethod MyScript.MyMethod -batchmode -quit

我们可以在启动Unity时调用我们自己的构建函数,即可开始构建。

如果有自定义的参数,可以通过System.Environment.GetCommandLineArgs()获取输入的参数,并做解析。

【工程自动检查】

检查主要分为代码检查和资源检查,可以在每次提交时做一次检查,也可以定时做一次全量检查。

代码检查
 可以分为编译检查、规范检查和缺陷检查

编译检查做起来做容易,可以针对每个人的每次提交做检查,主要针对漏提、错提、宏定义等导致的编译不通过情况

规范检查主要是看代码写的符不符合项目规范,虽然理论上有这一条,但实际上基本不会去做,因为每个项目组的规范不一样,要做自定义检查,而且这个检查也不好做,每个人编程习惯有细微差别,强制统一很难实施

缺陷检查很困难,一般会用第三方库做全量检查

通过检查的代码会被合并到主干,进行构建测试,这种频繁的将代码变更合并到主干中,然后自动构建和测试代码的过程叫做持续集成(CI,Continuous Integration)

通过检查后合并到主干一般在互联网开发中的做法,但在游戏中由于资产较重,构建时间很长,一般会直接将程序提交的代码合并到主干,然后再检查,且不会做构建测试

资源检查

凡是游戏内存在的资源,例如策划表、UI Prefab、场景Prefab、Timeline、动作资源、Mesh、各种精度模型、音频、各类配置等,都需要做检查。

可以做一个Unity全资源自动检查的系统,这些可以定时检查,本质上都是命令行启动Unity调用我们的检查方式,在不同的检查方法内实现不同的检查

自动通知

在构建或者检查过程中如果出现报错,我们会将报错信息输出到Log文件中。但是构建和检查一般是在单独的机器中执行的,每次去该机器上找Log文件既繁琐、效率又低,因此需要实现自动通知的功能。

将Log文件发送到某个服务器上进行存储,同时如果检查出错,可以直接将报错信息发送到工作群中的相关人员。

如果办公用的是飞书、钉钉或企业微信,其会提供API让我们去实现自动发消息。

【自动修改xcode工程】

使用Unity提供的PBXProject类,可以在代码中修改xcode工程的配置,示例如下:


public static void OnPostprocessBuild(BuildTarget buildTarget, string path)
{
    string projPath = path + "/Unity-iPhone.xcodeproj/project.pbxproj";
    PBXProject proj = new PBXProject();//创建PBXProject对象
    proj.ReadFromFile(projPath);

   //获取Target
    string target = proj.TargetGuidByName("Unity-iPhone");

    //设置自动签名
    proj.SetBuildProperty(target, "CODE_SIGN_IDENTITY", "Apple Development");
    proj.SetBuildProperty(target, "CODE_SIGN_STYLE", "Automatic");
    proj.SetTeamId(target, teamId); //teamId 是对应开发者正好的团队id (在苹果后台可以看到)

    //添加系统的FrameWork
    proj.AddFrameworkToProject(target, "AdSupport.framework", true);
    proj.AddFrameworkToProject(target, "CoreTelephony.framework", true);
    proj.AddFrameworkToProject(target, "StoreKit.framework", true); //内购需要 否则 
    PBXCapabilityType.InAppPurchase会加不上

    // 设置 BitCode
    proj.SetBuildProperty(target, "ENABLE_BITCODE", "false");
    // 设置 other link flags -ObjC
    proj.AddBuildProperty (target, "OTHER_LDFLAGS", "-ObjC");

    // 添加系统的tbd库
     string filePath = proj.AddFile("usr/lib/" + lib, "Frameworks/" + libPath, PBXSourceTree.Sdk);
      
    proj.AddFileToBuild(target, filePath);

    //添加自定义动态库
    string defaultLocationInProj = Application.dataPath+"/Editor/Plugins/iOS";                 
    //framework 存放的路径
    const string coreFrameworkName = "boxjing.framework";  // framework 的文件名
    string framework = Path.Combine(defaultLocationInProj, coreFrameworkName);
    string fileGuid = proj.AddFile(framework, "Frameworks/" + coreFrameworkName,         
       PBXSourceTree.Sdk);
    PBXProjectExtensions.AddFileToEmbedFrameworks(proj, target, fileGuid);
    proj.SetBuildProperty(target, "LD_RUNPATH_SEARCH_PATHS", "$(inherited)     
       @executable_path/Frameworks");
    
    //获取Plist文件
    string plistPath = path + "/Info.plist";
    PlistDocument plist = new PlistDocument();
    plist.ReadFromString(File.ReadAllText(plistPath));
    PlistElementDict infoDict = plist.root;

    infoDict.SetString("CFBundleShortVersionString",version);   //version
    infoDict.SetString("CFBundleVersion",build);                 //build

    //添加权限描述
    // 权限  根据自己的项目 修改后面的提示文案
    infoDict.SetString("NSLocationWhenInUseUsageDescription", "为了发现周围的好友,请允许App访问您的地里位置"); //地理位置
    infoDict.SetString("NSPhotoLibraryUsageDescription", "为了能选择照片进行上传,请允许App访问您的相册");      //相册
    infoDict.SetString("NSMicrophoneUsageDescription", "为了能够录制声音,请允许App访问您的麦克风权限");     //麦克风
    
    //添加URL Schemes白名单,LSApplicationQueriesSchemes是iOS中的一项权限设置,用于确定是否允许应用程序通过特定的URL Scheme与其他应用程序进行交互。URL Scheme是一种用于在应用程序之间传递数据和进行通信的方式
    PlistElementArray list = plist.root.CreateArray("LSApplicationQueriesSchemes");
    lsit.AddString("weixin");
    //同时添加Key和Value
     PlistElementDict dic = list.AddDict();
     dic.SetString("key","value")
    
    //获取unityframework
    string unityFramework = proj.GetUnityFrameworkTargetGuid();
}

xcode自动构建使用官方提供的xcodebuild,这方面的资源很多,就不多说了

【构建结果自动上传】

构建的结果不光是应用程序,还有Log文件,符号表等,这些文件都需要自动上传,而且上传的地方不一样。日常开发是一个环境,发布是另一个环境。

同时,还要将构建结果自动在群里通知。

这里只说了应该做哪些事情,实现起来都不难,就是流程繁琐些。

【定时任务】

python加强

上述用bat脚本实现了自动构建,但是后面还有构建结果自动上传、自动通知,其他各种繁琐细节的操作等,这时候用bat实现就很繁琐,我们可以用Phyton脚本实现,这些都是简单而固定的逻辑,如果不会写可以直接问GPT,下面是示例:

import subprocess
import time

def Init():
    print("初始化")

def run_unity_method(method_name):
    unity_path = "/path/to/Unity"  # Unity的安装路径
    project_path = "/path/to/UnityProject"  # Unity项目的路径

    command = unity_path + " -batchmode -projectPath " + project_path + " -executeMethod " + method_name
    subprocess.call(command, shell=True)


def xcode_build():
    print("xcode构建ipa")

def upload_build_result():
    upload_symbol_table()
    print("其他结果上传")
    print("上传构建结果")
    
def upload_symbol_table():
    # 在这里添加上传符号表的代码
    print("上传符号表")

def auto_notify():
     print("自动通知")

def main():
    Init()
    run_unity_method("YourNamespace.YourClassName.YourMethod")
    time.sleep(1)  # 等待1秒
    #如果是ios平台再加上xcode自动构建的
    xcode_build()
    #结果上传
    upload_build_result()
    #自动通知
    auto_notify()

if __name__ == "__main__":
    main()

随后我们只要在命令行中调用Phyton脚本即可

Jenkins加强

实际构建中要输入很多不同的参数,而我们的Phyton脚本中各种参数都固定,我们不可能在命令行中手动输入参数,同时还有一些定时任务等,这需要我们有一个可交互界面,可以用Jenkins

在Jenkins中输出参数,调用Phyton脚本,通过浏览器可以让不同的人都访问到Jenkins。当然Jenkins不止这些功能,但在游戏中其他功能用的不多。

到这一步,我们就完成了持续交付(CD,Continuous Delivery)

JenKins使用介绍

【应用自动安装】

应用自动安装启动是比较高级的功能,一般大型游戏安装下载耗时都在半小时以上,是很耗费时间的,可以在日常构建完成后自动安装启动以提高效率。

Android可以用adb指令通过usb或者wifi安装,同时做个apk监听新应用安装,并发出广播让新应用启动

ios可以使用阿里开源的tidevice

但这两种方式都比较繁琐,统一的解决方案是自己开发一个应用,模拟人工安装过程

【自助自动构建】

一般自动构建是在特定的机器上进行的,如果有人想自己构建验证东西,其会花费很长的时间在构建上。可以做一个自助构建的功能,让其他人借助已有的自动构建系统进行构建。

原理比较简单,先规定一些简单的指令映射自动构建时的参数,随后将这些指令转发给Jenkins即可,

【参考】

利用Unity提供的PBXObject来自动化iOS工程 - 简书

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/611561.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring AOP(2)

目录 Spring AOP详解 PointCut 切面优先级Order 切点表达式 execution表达式 切点表达式示例 annotation 自定义注解MyAspect 切面类 添加自定义注解 Spring AOP详解 PointCut 上面代码存在一个问题, 就是对于excution(* com.example.demo.controller.*.*(..))的大量重…

Tomcat中服务启动失败,如何查看启动失败日志?

1. 查看 localhost.log 这个日志文件通常包含有关特定 web 应用的详细错误信息。运行以下命令查看 localhost.log 中的错误&#xff1a; sudo tail -n 100 /opt/tomcat/latest/logs/localhost.YYYY-MM-DD.log请替换 YYYY-MM-DD 为当前日期&#xff0c;或选择最近的日志文件日…

【notepad++】使用

1 notepad 下载路径 https://notepad-plus.en.softonic.com/download 2 设置护眼模式 . 设置——语言格式设置——前景色——黑色 . 背景色——RGB &#xff1a;199 237 204 . 勾选“使用全局背景色”、“使用全局前景色” . 保存并关闭

YOLOv5改进 | 注意力机制 | 理解全局和局部信息的SE注意力机制

在深度学习目标检测领域&#xff0c;YOLOv5成为了备受关注的模型之一。本文给大家带来的是能够理解全局和局部信息的SE注意力机制。文章在介绍主要的原理后&#xff0c;将手把手教学如何进行模块的代码添加和修改&#xff0c;并将修改后的完整代码放在文章的最后&#xff0c;方…

RAG查询改写方法概述

在RAG系统中&#xff0c;用户的查询是丰富多样的&#xff0c;可能存在措辞不准确和缺乏语义信息的问题。这导致使用原始的查询可能无法有效检索到目标文档。 因此&#xff0c;将用户查询的语义空间与文档的语义空间对齐至关重要&#xff0c;目前主要有查询改写和嵌入转换两种方…

代码随想录算法训练营第六十天| LeetCode647. 回文子串 、516.最长回文子序列

一、LeetCode647. 回文子串 题目链接/文章讲解/视频讲解&#xff1a;https://programmercarl.com/0647.%E5%9B%9E%E6%96%87%E5%AD%90%E4%B8%B2.html 状态&#xff1a;已解决 1.思路 这道题我只想出来了暴力解法&#xff0c;动规解法并没有想出来。根据视频讲解才把它想出来。…

【hackmyvm】 Animetronic靶机

靶机测试 arp-scanporturl枚举exiftool套中套passwordsudo 提权 arp-scan arp-scan 检测局域网中活动的主机 192.168.9.203 靶机IP地址port 通过nmap扫描&#xff0c;获取目标主机的端口信息 ┌──(root㉿kali)-[/usr/share/seclists] └─# nmap -sT -sV -O 192.16…

基于springboot+vue+Mysql的体质测试数据分析及可视化设计

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…

C语言/数据结构——(相交链表)

一.前言 今天在力扣上刷到了一道题&#xff0c;想着和大家一起分享一下这道题——相交链表https://leetcode.cn/problems/intersection-of-two-linked-lists废话不多说&#xff0c;让我们开始今天的分享吧。 二.正文 1.1题目描述 是不是感觉好长&#xff0c;我也这么觉得。哈…

【智能优化算法】蜜獾优化算法(Honey Badger Algorithm,HBA)

蜜獾优化算法(Honey Badger Algorithm,HBA)是期刊“MATHEMATICS AND COMPUTERS IN SIMULATION”&#xff08;IF 3.6&#xff09;的2022年智能优化算法 01.引言 蜜獾优化算法(Honey Badger Algorithm,HBA)受蜜獾智能觅食行为的启发&#xff0c;从数学上发展出一种求解优化问题的…

Linux修炼之路之初识操作系统+基础指令(1)

目录 引言 一&#xff1a;对操作系统(OS)的简单了解 1.操作系统(OS) 是什么 2.操作系统好坏的衡量标准 3.操作系统存在的重要性 4.理解所有在计算机上的操作 二&#xff1a;Linux与windows操作的特点区别 三&#xff1a;基础指令 1.ls 指令 1.使用 2.常用选项 2.…

【17-Ⅰ】Head First Java 学习笔记

HeadFirst Java 本人有C语言基础&#xff0c;通过阅读Java廖雪峰网站&#xff0c;简单速成了java&#xff0c;但对其中一些入门概念有所疏漏&#xff0c;阅读本书以弥补。 第一章 Java入门 第二章 面向对象 第三章 变量 第四章 方法操作实例变量 第五章 程序实战 第六章 Java…

linux进阶篇:Nginx反向代理原理与案例详解

Linux服务搭建篇&#xff1a;Nginx反向代理原理与案例详解 一、什么是正向代理 举个栗子&#xff1a; 我们在校外、公司外&#xff0c;是访问不到学校、公司的内网的&#xff0c;但是我们想要访问内网资源时&#xff0c;会用到VPN。而一般内网会存在一个VPN服务器&#xff0c…

安装vmware station记录

想学一下linux,花了3个多小时&#xff0c;才配置好了&#xff0c;记录一下 安装vm12,已配置linux系统 报错&#xff0c;VMware Workstation 与 Device/Credential Guard 不兼容解决方案&#xff0c;网上说有不成功的&#xff0c;电脑蓝屏&#xff0c;选择装vm16试试 vm16 在…

运维开发工程师教程之MongoDB单机版设置

MongoDB单机版设置 一、创建虚拟机 在VMware Workstation软件中新建一个虚拟机&#xff0c;具体操作步骤如下&#xff1a; ①运行VMware Workstation软件&#xff0c;进入到主界面&#xff0c;单击“创建新的虚拟机”来创建新的虚拟机&#xff0c;如图3-1所示。 图3-1 VMware…

算法设计与分析 动态规划/回溯

1.最大子段和 int a[N]; int maxn(int n) {int tempa[0];int ans0;ansmax(temp,ans);for(int i1;i<n;i){if(temp>0){tempa[i];}else tempa[i];ansmax(temp,ans);}return ans; } int main() {int n,ans0;cin>>n;for(int i0;i<n;i) cin>>a[i];ansmaxn(n);co…

智慧之巅:大数据与算力中心的融合演进

智慧之巅&#xff1a;大数据与算力中心的融合演进 1 引言 在这个数据驱动的时代&#xff0c;我们站在了一个前所未有的历史节点上。大数据和算力中心&#xff0c;这两个曾经各自为政的领域&#xff0c;如今正以一种前所未有的方式交织在一起&#xff0c;共同推动着数字经济的蓬…

PDF高效编辑:一键批量,PDF转图片的快速解决方案

在数字化时代&#xff0c;PDF文件已成为工作和学习中不可或缺的一部分。然而&#xff0c;有时我们可能需要将PDF转换为图片&#xff0c;以便更轻松地编辑、共享或处理。为了满足这一需求&#xff0c;许多高效的PDF编辑工具应运而生&#xff0c;其中“办公提效工具”一键批量PDF…

C++对象的拷贝构造函数

如果一个构造函数的第一个参数是类本身的引用,且没有其它参数(或者其它的参数都有默认值),则该构造函数为拷贝构造函数。 拷贝(复制)构造函数:利用同类对象构造一个新的对象 ●1.函数名和类同名 (构造函数) ●2.没有返回值 (构造函数) ●3.第一个参数必…

【甲辰雜俎】世界上最不可靠的就是人

"世界上最不可靠的就是人" 人是一個多元的複變函數, 今天經受住考驗, 明天你就有可能叛變。 過去是戰場上的仇敵, 明天就有可能成為政治上的盟友。 —— 擷取自電視劇《黑冰》 人的不可預測性, 的確是一個普遍的現象。 每個人都是一個獨特的個體, 受到不同的…