原地址:http://www.xuanyusong.com/archives/2418#comments

最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的机器,可能还有不同的渠道包,不同渠道可能用的SDK都不一样,这一切的一切都表明你的代码无法做到自适应的,除非批量打包提供各个平台的预定义标签#define 。

Unity默认提供了一些预定义标签如:

UNITY_EDITOR  : 编辑器模式下。

UNITY_STANDALONE:PC Mac Linux模型下。

UNITY_IPHONE:IOS模式下。

UNITY_ANDROID:ANDROID模式下。

还有很多预定义标签、大家可以在这里看到:http://docs.unity3d.com/Documentation/Manual/PlatformDependentCompilation.html

         官方提供的标签属于比较大的范围标签,比如我希望在UNITY_ANDROID下面在写一些自定义的标签、类似 QQ UC CMCC这样的渠道标签该如何呢?如下图所示,ProjectSetting打包界面每个平台都会有Scripting Define Symbols这个选项,可以在这里添加每个平台下对应的自定义标签(多个标签用“;”号隔开),这里我设置的是Android平台,如果IOS也需要打这样的渠道标签那么也要在IOS页面Scripting Define Symbols选项处添加对应的标签。

标签做出来了就好办了,然后在代码中我们可以这样来写。如果在Scripting Define Symbols中没有出现的标签默认是不启用的,就像 #define Test 一样,会自动被注释掉。

然后我们看看如何实现脚本批量打包。

 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
 
public class MyEditorScript  
{
        //得到工程中所有场景名称
        static string[] SCENES = FindEnabledEditorScenes();
        //一系列批量build的操作
        [MenuItem ("Custom/Build Android QQ")]
        static void PerformAndroidQQBuild ()
        {  
                 BulidTarget("QQ","Android");
        }
 
        [MenuItem ("Custom/Build Android UC")]
        static void PerformAndroidUCBuild ()
        {  
                 BulidTarget("UC","Android");
        }
 
        [MenuItem ("Custom/Build Android CMCC")]
        static void PerformAndroidCMCCBuild ()
        {  
                 BulidTarget("CMCC","Android");
        }
 
        [MenuItem ("Custom/Build Android ALL")]
        static void PerformAndroidALLBuild ()
        {  
              BulidTarget("QQ","Android");
                 BulidTarget("UC","Android");
              BulidTarget("CMCC","Android");
        }
        [MenuItem ("Custom/Build iPhone QQ")]
       static void PerformiPhoneQQBuild ()
        {  
                 BulidTarget("QQ","IOS");
        }
 
        [MenuItem ("Custom/Build iPhone QQ")]
       static void PerformiPhoneUCBuild ()
        {  
                 BulidTarget("UC","IOS");
        }    
 
       [MenuItem ("Custom/Build iPhone CMCC")]
       static void PerformiPhoneCMCCBuild ()
        {  
                 BulidTarget("CMCC","IOS");
        }    
 
        [MenuItem ("Custom/Build iPhone ALL")]
        static void PerformiPhoneALLBuild ()
        {  
              BulidTarget("QQ","IOS");
                 BulidTarget("UC","IOS");
              BulidTarget("CMCC","IOS");
        }
 
        //这里封装了一个简单的通用方法。
        static void BulidTarget(string name,string target)
        {
               string app_name = name;
               string target_dir = Application.dataPath + "/TargetAndroid";
               string target_name = app_name + ".apk";
               BuildTargetGroup targetGroup = BuildTargetGroup.Android;
               BuildTarget buildTarget = BuildTarget.Android;
               string applicationPath =     Application.dataPath.Replace("/Assets","");
 
                if(target == "Android")
                {
                     target_dir = applicationPath + "/TargetAndroid";
                     target_name = app_name + ".apk";
                     targetGroup = BuildTargetGroup.Android;
                }
                if(target == "IOS")
                {
                     target_dir = applicationPath + "/TargetIOS";
                     target_name = app_name;
                     targetGroup = BuildTargetGroup.iPhone;
                     buildTarget = BuildTarget.iPhone;
                }
 
                //每次build删除之前的残留
                if(Directory.Exists(target_dir))
                     {
                          if (File.Exists(target_name))
                             {
                                File.Delete(target_name);
                           }
                   }else
                {
                    Directory.CreateDirectory(target_dir);
                }
 
                //==================这里是比较重要的东西=======================
                switch(name)
                {
                case "QQ":
                        PlayerSettings.bundleIdentifier = "com.game.qq";
                        PlayerSettings.bundleVersion = "v0.0.1";
                        PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup,"QQ");  
                    break;
                case "UC":
                        PlayerSettings.bundleIdentifier = "com.game.uc";
                        PlayerSettings.bundleVersion = "v0.0.1";
                        PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup,"UC");                        
                    break;
                case "CMCC":
                        PlayerSettings.bundleIdentifier = "com.game.cmcc";
                        PlayerSettings.bundleVersion = "v0.0.1";
                        PlayerSettings.SetScriptingDefineSymbolsForGroup(targetGroup,"CMCC");                        
                    break;
                }
 
                //==================这里是比较重要的东西=======================
 
                 //开始Build场景,等待吧~
                 GenericBuild(SCENES, target_dir + "/" + target_name, buildTarget,BuildOptions.None);
 
        }
 
    private static string[] FindEnabledEditorScenes() {
        List<string> EditorScenes = new List<string>();
        foreach(EditorBuildSettingsScene scene in EditorBuildSettings.scenes) {
            if (!scene.enabled) continue;
            EditorScenes.Add(scene.path);
        }
        return EditorScenes.ToArray();
    }
 
        static void GenericBuild(string[] scenes, string target_dir, BuildTarget build_target, BuildOptions build_options)
        {  
                EditorUserBuildSettings.SwitchActiveBuildTarget(build_target);
                string res = BuildPipeline.BuildPlayer(scenes,target_dir,build_target,build_options);
 
                if (res.Length > 0) {
                        throw new Exception("BuildPlayer failure: " + res);
                }
        }
 
}

这里面忘说了一点,如果我们希望在性能高的手机上用一套好的资源,在性能低的手机上用一套差一点的资源该怎么办?那么首先我们先搞清楚Unity会把什么资源打包,什么资源不打包?

1.Resources文件夹 

Resources文件夹是一个只读的文件夹,通过Resources.Load()来读取对象。因为这个文件夹下的所有资源都可以运行时来加载,所以Resources文件夹下的所有东西都会被无条件的打到发布包中。建议这个文件夹下只放Prefab或者一些Object对象,因为Prefab会自动过滤掉对象上不需要的资源。举个例子我把模型文件还有贴图文件都放在了Resources文件夹下,但是我有两张贴图是没有在模型上用的,那么此时这两张没用的贴图也会被打包到发布包中。假如这里我用Prefab,那么Prefab会自动过滤到这两张不被用的贴图,这样发布包就会小一些了。 

2.StreamingAssets

StreamingAssets文件夹也是一个只读的文件夹,但是它和Resources有点区别,Resources文件夹下的资源会进行一次压缩,而且也会加密,不使用点特殊办法是拿不到原始资源的。但是StreamingAssets文件夹就不一样了,它下面的所有资源不会被加密,然后是原封不动的打包到发布包中,这样很容易就拿到里面的文件。所以StreamingAssets适合放一些二进制文件,而Resources更适合放一些GameObject和Object文件。StreamingAssets 只能用过www类来读取!!

3. 最后凡是在Hierarchy视图对象引用过的资源文件也会被无条件打包到发布包中。如果有一部分文件可能没有在Resources文件夹下也没有在StreamingAssets文件夹下,也没有被Hierarchy视图游戏对象引用,那么这类资源是不会被打包到发布包中的。

OK!搞清楚这一点就好办了!在处理不同包对应不同资源包的时候,尽量让可配置的资源放在Resources 或StreamingAssets文件夹下,运行的时候程序动态的来读取它们,最后显示在游戏中就可以了。在批量打包前,在Project视图下创建不同包的资源文件夹, 然后脚本 AssetDatabase 动态的将资源拷贝至Resources或StreamingAssets 文件夹中,

http://docs.unity3d.com/Documentation/Manual/StreamingAssets.html

 
1
2
3
4
5
6
7
8
        [MenuItem ("Custom/Build Android QQ")]
        static void PerformAndroidQQBuild ()
        {  
                         //先把资源拷贝到Resources或者StreamingAssets
            AssetDatabase.CopyAsset("path","newPath");
                         //然后开始编译版本
                BulidTarget("QQ","Android");
        }

代码中说到还有一个重要的东西就是PlayerSettings类。因为在Build的时候不同平台下可能会有一些PlatformSettings是不一样的,所以需要在脚本里面动态的设置它,强大的参数列表在这里:http://docs.unity3d.com/Documentation/ScriptReference/PlayerSettings.html根据情况来批量构建自己的工程吧~

另外,由于IOS工程比较特殊,使用这样的方法我们只能生成出来多个IOS的工程文件,但是这并不是最终发布的版本。如果想一键生成.ipa文件的话。

1.通过命令行来Build IOS  http://docs.unity3d.com/Documentation/Manual/CommandLineArguments.html

2.通过shell来自动打包 1生成的xcode工程,最终生成渠道包。

这两种方法我已经在网上找到了答案,今天太晚了就不在研究了,下一篇的时候我在补上。 祝大家学习愉快!!不早了,晚安!欢迎大家一起来讨论与学习,嘿嘿!!!

代码下载地址:http://vdisk.weibo.com/s/HUf2W

Unity3D研究院之脚本批量打包渠道包研究的更多相关文章

  1. Unity3D脚本批量打包渠道包

    最近在研究Unity3D脚本批量打包,比如在Android平台下各种不同分辨率和不同内存大小的机器,可能还有不同的渠道包,不同渠道可能用的SDK都不一样,这一切的一切都表明你的代码无法做到自适应的,除 ...

  2. Unity3D研究院之IOS全自动打包生成ipa

    接着上一篇文章, 自动生成framework,这篇文章我把shell自动化打包ipa整理了一下,希望大家喜欢,嘿嘿.. 建议大家先看一下上一篇文章.http://www.xuanyusong.com/ ...

  3. Ant build.xml 批量打渠道包回顾!打第三方jar包总结

    配置: eclipse3.9 + ADT22 + sdk 4.0 eclipse带自动混淆的,不过只有在我们手动创建包的时候,才去打签名,去混淆! 开启混淆这样做吧! 必备文件3个: 当然进行ant打 ...

  4. Unity3D研究院之脚本生成Android Google Project

    一般安卓自动化打包直接会生成个APK出来,但是我不想生成APK,我想生成Eclipse项目. 然后在自动化完成后面的打包工作.     1 2 3 4 5 6 7 8 9 10 11 using Un ...

  5. Unity3D研究院之自制批量关联材质与贴图插件

    原地址:http://www.xuanyusong.com/archives/2314 美术做过的模型导出fbx,美术把Fbx和贴图文件给了程序,程序把Fbx导入工程可能会出现贴图和材质没有关联上的问 ...

  6. Android-Ant自动编译打包android项目 -- 2 ----签名与渠道包

    上篇介绍了怎么使用ant自动编译打包现有的android项目,这篇将继续介绍如果如何在ant打包应用的时候加入签名信息以及自动打包渠道包. 1. 加入签名信息: 在项目的根目录下建一个ant.prop ...

  7. Unity3D研究院之Jenkins的使用(七十八)

    长夜漫漫无心睡眠,来一篇嘿嘿.我相信如果已经用Shell脚本完成IOS和Android打包的朋友一定需要Jenkins 怎么才能让策划打包ipa和apk?怎么才能彻底省去程序的时间,只要在同一局域网内 ...

  8. cocos2d-x使用ant批量打包

    当项目需要在多渠道上线时,要打很多的渠道包,少则几十个,多种几百个.它们的区别一般只是渠道id或部分配置信息不同,这些信息均可写在配置文件中. 例如常见的渠道id不同,一般定义在AndroidMani ...

  9. Android批量打包-如何一秒内打完几百个apk渠道包

    在国内Android常用渠道可能多达几十个,如: 谷歌市场.腾讯应用宝.百度手机助手.91手机商城.360应用平台.豌豆荚.安卓市场.小米.魅族商店.oppo手机.联想乐商.中兴汇天地.华为.安智.应 ...

随机推荐

  1. 洛谷 P2670 扫雷游戏==Codevs 5129 扫雷游戏

    题目描述 扫雷游戏是一款十分经典的单机小游戏.在n行m列的雷区中有一些格子含有地雷(称之为地雷格),其他格子不含地雷(称之为非地雷格).玩家翻开一个非地雷格时,该格将会出现一个数字——提示周围格子中有 ...

  2. ZigBee安全相关

    ZigBee安全由AES加密算法和CCM操作方式作为安全方案,广泛使用在ZigBee联盟的通信协议中.ZDO层负责安全策略和安全配置的管理. Technorati 标签: ZigBee 安全 2. 配 ...

  3. C++ 重载new和delete操作符

    原因: C++标准库提供的new和delete操作符,是一个通用实现,未针对具体对象做具体分析 存在分配器速度慢.小型对象空间浪费严重等问题,不适用于对效率和内存有限制的应用场景   好处: 灵活的内 ...

  4. SASS语法备忘

    sass语法 关于sass 3.3.0更新说明——3.3.0 sublime相关插件为:scss语法高亮,sass语法高亮,编译,保存即编译,格式化 文件后缀名 sass有两种后缀名文件:一种后缀名为 ...

  5. mac OS X下制定ll指令

    ll作为ls -l的快捷方式,但系统本身没有,需要通过如下方法生成 1.在用户目录下新建.bash_profile文件 # vim .bash_profile 2.添加内容 alias ll = 'l ...

  6. js阻止冒泡事件及默认操作

    1. 事件目标 现在,事件处理程序中的变量event保存着事件对象.而event.target属性保存着发生事件的目标元素.这个属性是DOM API中规定的,但是没有被所有浏览器实现 .jQuery对 ...

  7. 关于angularJS与jquery在使用上的一些感悟

    最近做的项目中,有同时用到angularJS与jquery两种JS框架. 在使用过程中发现,angularJS的用法更像是面向对象的编程模式.它会要求你定义一个view model,然后所有的页面变化 ...

  8. Android如何设置标题栏的高度

    转载自: http://blog.csdn.net/yuxiaohui78/article/details/8222993 新建一个styles.xml 1 <?xmlversion=" ...

  9. Delphi XE5教程12:注释和编译器指示字

    内容源自Delphi XE5 UPDATE 2官方帮助<Delphi Reference>,本人水平有限,欢迎各位高人修正相关错误!也欢迎各位加入到Delphi学习资料汉化中来,有兴趣者可 ...

  10. java 下载spring的方法

    spring是很好用,可惜的是,貌似现在没有办法从网站上找到整合在一起的包了... 我以前只能通过maven去抓... 今天终于知道了一个方法: 访问如下地址: http://repo.spring. ...