基于Python和Jenkins的Unity自动化打包方案总结(2)

622 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情

Unity端C#打包代码框架

Unity端的打包系统包含的内容上一篇已经说了,简单来说,本质上是要调用BuildPlayer去打版本包。而为了实现这个最终目的,需要获取打包参数进行各种准备工作。因此C#打包脚本大概可以分成几个部分:

  • 打包参数类定义
  • 命令行解析和打包参数获取
  • 根据打包参数修改代码预处理定义,选择不同的资源和不同的Unity场景
  • 执行打包并进行后续处理

打包参数类定义

为了自定义,我们需要设置打包参数,因此有必要将所有的参数定义在一个类里面,方便参数的构造和传递。这儿给一个例子:

namespace CustomBuilder
{
    public enum BuildOS
    {
        Windows,
        Mac,
        iOS,
        Android
    }

    public enum BuildStore
    {
        Default,
        Steam,
        Google,
        Apple
    }

    public class BuildConfig
    {
        public string AppName = "AppName";
        public BuildOS OS = BuildOS.Windows;
        public BuildStore Store = BuildStore.Default;

        public string VersionBase = "0.1.0";
        public int SvnReversion = 1;

        //for filename and path
        public string VersionType = "Beta";
        public string BuildDateTime = null;
        public string OutputFolder = null;

        //for compile
        public bool DevelopmentMode = false;

        public string[] BuildScenes = null;                                
    }    
}

BuildConfig类中的成员就是需要设置的打包参数,这个是根据业务需求进行定义的。我这儿给出了一些常用的参数。

命令行参数解析和参数获取

打包的第一步就是获取命令行参数,以及打包参数。在我们的系统中,我们只获取一个命令行参数,这个参数就是包含所有打包参数的json文件,然后解析这个文件获取到打包参数。我们使用一个单独的类去做这个工作:


using UnityEngine;
using CustomBuilder;
using System.IO;
using System;

public class BuilderCommandline 
{    
    public static void Build_SwitchEnv()
    {
        var config = LoadBuildConfigFromJson(ParseCommandLine());
        MainBuilder.Config = config;
        MainBuilder.Build_SwitchEnv();                
    }

    public static void Build_MakePackage()
    {
        var config = LoadBuildConfigFromJson(ParseCommandLine());
        MainBuilder.Config = config;
        MainBuilder.Build_MakePackage();
    }

    static string ParseCommandLine()
    { 
        string configFilePath = null;      

        string[] strs = System.Environment.GetCommandLineArgs();
        foreach (var s in strs)
        {                        
            if (s.Contains("-configFilePath:"))
            {
                int sidx = s.IndexOf(":");
                if (sidx >= 0)
                {
                    string arg = s.Substring(sidx + 1);                    
                    configFilePath = arg;                    
                }              
            }                        
        }

        return configFilePath;
    }
    
    public static BuildConfig LoadBuildConfigFromJson(string jsonPath)
    { 
        BuildConfig config = default;

        if(File.Exists(jsonPath))
        {
            try{
                string dataRead = "";
                using(FileStream stream = new FileStream(jsonPath, FileMode.Open))
                {
                    using(StreamReader reader = new StreamReader(stream))
                    {
                        dataRead = reader.ReadToEnd();
                    }
                }

                config = JsonUtility.FromJson<BuildConfig>(dataRead);                
            }
            catch(Exception e)
            {
                Debug.LogError($"Failed to load build config from file {jsonPath}. Exception:{e}");
            }
        }
        
        return config;
    }    
}

该类是和Unity命令行交互的接口,它包含两个打包方法:Build_SwitchEnvBuild_MakePackage。因为我们在打包过程中要修改程序的预编译定义,这会导致Domain Reload,如果没有reload完成就直接执行BuildPlayer会有一定的几率造成打出的版本crash。这个在Unity论坛上有相关的讨论:forum.unity.com/threads/lev… 因此这儿使用两个独立的打包方法,分别使用Unity命令行执行。如果打包过程中需要执行Addressable build,那么还需一个独立的打包方法用于Make Addressable。

解析命令行参数

详见代码中的ParseCommandLine方法,这儿我们只需要解析一个参数configFilePath。

解析Json文件

详见代码中的LoadBuildConfigFromJson方法。使用FileStream打开文件,使用StreamReader读取,之后使用JsonUtility.FromJson<BuildConfig>(dataRead);方法直接从Json数据中解析出我们上面定义的BuildConfig类。

调用实际的打包方法

Build_SwitchEnv为例,将解析出的Config对象设置为MainBuilder的当前使用的Config,并且调用MainBuilder.Build_SwitchEnv()进行实际的操作。MainBuilder是我们的核心打包类,会根据设置的参数,根据游戏的实际业务逻辑对代码和资源进行处理。Build_SwitchEnv是根据当前的OS和Store等参数切换代码的环境,也就是设置不同的预编译定义。

小结

本篇中我们首先介绍了C#端的打包代码的结构,并详细说明了打包参数的定义,打包命令行参数的获取和打包参数的解析,并给出一个实际的例子。下篇中我们讲实际分析最重要的核心打包类MainBuilder。