Unity3D打包android游戏

作者: 键盘上的麒麟臂 | 来源:发表于2019-03-08 12:10 被阅读18次

    平时我们都会用手机玩游戏,而有些方式是用Unity3D来开发的。这次我们来探究一下,Unity3D的android游戏是怎么形成的。

    一.配置开发环境

    首先要说明的一点是unity3D游戏的打包不是android接入游戏内容打包的,而是游戏接入android内容打包的,就是说一般是在unity中进行打包,而不是在androidstudio中,当然也可以在unity中导出项目用androidstudio打包。

    首先下载unity开发环境。



    在官网找到穷B版下载,然后跟着流程安装就行,如果没有Visual Studio的话,在安装过程中会顺便帮你安装,至少我下载的版本是这个的,环境大概占4G多内存,一定要留出足够的空间。


    打开后发现主要分两部分,上面是画布,下面是放脚本。

    之后打开AndroidStudio,准备写代码。

    二.Unity3D对接android

    两块的对接,主要是把android代码丢到Unity中,android代码可以打jar包,也可以打aar,我这里主要讲jar包

    1.android部分

    先说说android部分,要让unity游戏展示在android的Activity中,需要让这个Activity继承UnityPlayerActivity。当然我们默认的androidSDK中是没有这个类的,我们可以从之前下载的unity中找到。
    这个包的位置在
    你下的unity的文件\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes


    把这个jar包放到android项目中引用就行。还需要注意的一点是这个包的路径不一定在这个文件夹下,我不能保证之后的版本不会变,当前我用的版本是在这里,但不管怎样都可以在Unity中找到。
    我android端的代码很简单,就写一个方法用Log打印一句话。
    public class MainActivity extends UnityPlayerActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        }
    
        public void say(String str){
            Log.v("mmp",str);
        }
    
    }
    

    还需要注意的一点是,这个Activity是供Unity的游戏展示的,所有不能写setContentView方法,不然显示的就是本地的xml页面

    这样android端就写完了,之后我们打jar包。在gradle中加入jar包命令

    task makeJar(type: Jar) {
        archiveName = 'wang.jar' //最终jar包的名称
        from(project.zipTree('build/intermediates/packaged-classes/release/classes.jar')) //需要打的juhepaysdk的编译文件
        destinationDir = file('build/libs') //jar包输出路径
    }
    makeJar.dependsOn(build)
    

    关于打jar包,很多人之前说在以前的bundle目录中找不到classes.jar,是因为现在的classes.jar换成了在packaged-classes目录下,而且我们也依然不能保证以后的版本不会换,反正找不到的话可以自己在intermediates目录下找。
    还有一点是我仅仅打了代码到jar包中,没有和引用到的jar包一起打,因为引用的包可以直接扔到unity中,没必要一起打包,之前网上也有人说一起打也不会影响。
    打完jar包之后android这边算是完成了,接下来看看unity端要怎么做处理。

    2.unity部分

    我们先画图,关于Unity3D其实我不太知道怎么用,但是画一个Button还是难不倒的。



    右键Canvas然后选UI再选Button,在右边栏可以选择这个UI的属性。


    我们先把这个unity的范围设置成我们手机的范围,这个会更清楚的看出按钮显示在手机上的预览图。按照图中的顺序设置



    在中间的预览窗口点击Game,并且在图中的位置设置尺寸,我这里设置1920 x 1080竖屏,然后把按钮拖到中间。

    这样我们算是把图简单画好了,接下来我们给控件设置脚本。我对Unity的开发不是很了解,但是好像他能为每个对象设置一个脚本。我们用C#写一个脚本设置给上面的Canvas对象,这样这个对象就能执行这个脚本,注意是设置给最外层的Canvas对象而不是里面的Button对象。

    (1)先写C#脚本
    public class Test : MonoBehaviour
    {
    
        private AndroidJavaClass jc;
        private AndroidJavaObject jo;
        // Start is called before the first frame update
        void Start()
        {
            jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    
            GameObject btnObj = GameObject.Find("Canvas/Button");
            Button btn = (Button)btnObj.GetComponent<Button>();
            btn.onClick.AddListener(onClick);
    
        }
    
        void onClick()
        {
            jo.Call("say", "fuck");
        }
    
        // Update is called once per frame
        void Update()
        {
            
        }
    }
    

    不懂C#也没关系,至少写一个点击事件还难不倒我们,代码中脚本名为Test,AndroidJavaClass和AndroidJavaObject是C#和java通讯的类,这两个类的命名真的是教科书般的命名。

            jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
    

    获取到android类是这样的固定写法,调用类中的方法用Call函数,第一个参数是java那边定义的方法名,后面的参数是方法的参数。

            GameObject btnObj = GameObject.Find("Canvas/Button");
            Button btn = (Button)btnObj.GetComponent<Button>();
            btn.onClick.AddListener(onClick);
    

    这里是获取到Canvas下的Button对象,然后设置点击事件。这里只是简单的讲,有兴趣的可以自己去找详细的API。

    代码写好之后把脚本添加给Canvas。



    点击1中的Add Component,选着Test脚本,添加后就像2一样显示。同样,如果想移除脚本的话可以右键2的地方选着移除。

    这样就把脚本添加成功了。那么现在是怎样的情况呢?点击按钮,就会执行脚本中的监听事件,调用AndroidJavaObject的Call方法,调用到android中的say方法。

    最后,我们需要把android中的内容添加到unity中,最后打包的时候才会一起打进去。



    如图一样,在Assets中创建Plugin文件夹,在创建Android文件夹,下面创建libs和res。



    libs中放入wang.jar,就是我们上面打的包,wang.jar里面是不是调用了android的东西,我这里用的是v4,所以要把一个android的v4包也放进去,不是也用了unity的jar吗?没错,但是这个在打包时会提供,所以这里我们没必要重复放unity的jar包进去。注意了,不放unity的jar包进去。
    res下就放android项目中res下的内容。

    最后还要把manifest文件放到android文件夹下



    这样就只剩最后的打包了。

    三.打包

    上边已经把android的内容加到unity中了,我们就可以在Unity中打android的apk包了。
    还是多说一句,记得要在Edit -》Preferences -》External Tools中设置SDK路径


    打包方法是点击File -》 Build Settings



    选着player setting,在3中设置得和项目中的gradle一样。
    可以看出在Build System中选中的是Gradle,所以unity最后会调用Gradle工具来进行打包。
    打包过程中如果出错的话,可以在Console中查看错误日志


    这里再讲一个比较坑的地方
    我第一次打包时报了一个错,报文件重复。

    CommandInvokationFailure: Gradle build failed. 
    D:\u3d\Editor\Data\PlaybackEngines\AndroidPlayer/Tools\OpenJDK\Windows\bin\java.exe -classpath "D:\u3d\Editor\Data\PlaybackEngines\AndroidPlayer\Tools\gradle\lib\gradle-launcher-4.6.jar" org.gradle.launcher.GradleMain "-Dorg.gradle.jvmargs=-Xmx4096m" "assembleRelease"
    
    stderr[
    D8: Program type already present: com.example.kylin.androidunitydemo.BuildConfig
    java.lang.RuntimeException: java.lang.RuntimeException: com.android.builder.dexing.DexArchiveMergerException: Error while merging dex archives: D:\testu3d\TestOne\Temp\gradleOut\build\intermediates\transforms\dexBuilder\release\8, D:\testu3d\TestOne\Temp\gradleOut\build\intermediates\transforms\externalLibsDexMerger\release\0, D:\testu3d\TestOne\Temp\gradleOut\build\intermediates\transforms\dexBuilder\release\7.jar
    Program type already present: com.example.kylin.androidunitydemo.BuildConfig
    Learn how to resolve the issue at https://developer.android.com/studio/build/dependencies#duplicate_classes.
    

    我按照提示找到文件夹,发现重复的文件是BuildConfig。于是我的做法是把jar包的BuildConfig删除(先解压,再删除,再压缩)就正常了,合着unity打包的时候还会给你打进去一个BuildConfig。
    虽然我能解决了这个问题,但不知道有没有更好的方法,不然难道每次都要删除jar包的文件吗,这样岂不是很麻烦。

    按照上面的操作,我们就能打出一个可以运行的apk文件了,我测试过可以运行,Gif软件被我删了,这里就不演示了,不过我们可以反编译看看unity做处理之后的结构。可以看出多了很多文件。


    相关文章

      网友评论

        本文标题:Unity3D打包android游戏

        本文链接:https://www.haomeiwen.com/subject/ukwlpqtx.html