Unity3D打包android游戲

平時我們都會用手機玩游戲,而有些方式是用Unity3D來開發(fā)的。這次我們來探究一下,Unity3D的android游戲是怎么形成的。

一.配置開發(fā)環(huán)境

首先要說明的一點是unity3D游戲的打包不是android接入游戲內(nèi)容打包的,而是游戲接入android內(nèi)容打包的,就是說一般是在unity中進行打包,而不是在androidstudio中,當然也可以在unity中導出項目用androidstudio打包。

首先下載unity開發(fā)環(huán)境。



在官網(wǎng)找到窮B版下載,然后跟著流程安裝就行,如果沒有Visual Studio的話,在安裝過程中會順便幫你安裝,至少我下載的版本是這個的,環(huán)境大概占4G多內(nèi)存,一定要留出足夠的空間。


打開后發(fā)現(xiàn)主要分兩部分,上面是畫布,下面是放腳本。

之后打開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)

關(guān)于打jar包,很多人之前說在以前的bundle目錄中找不到classes.jar,是因為現(xiàn)在的classes.jar換成了在packaged-classes目錄下,而且我們也依然不能保證以后的版本不會換,反正找不到的話可以自己在intermediates目錄下找。
還有一點是我僅僅打了代碼到j(luò)ar包中,沒有和引用到的jar包一起打,因為引用的包可以直接扔到unity中,沒必要一起打包,之前網(wǎng)上也有人說一起打也不會影響。
打完jar包之后android這邊算是完成了,接下來看看unity端要怎么做處理。

2.unity部分

我們先畫圖,關(guān)于Unity3D其實我不太知道怎么用,但是畫一個Button還是難不倒的。



右鍵Canvas然后選UI再選Button,在右邊欄可以選擇這個UI的屬性。


我們先把這個unity的范圍設(shè)置成我們手機的范圍,這個會更清楚的看出按鈕顯示在手機上的預覽圖。按照圖中的順序設(shè)置



在中間的預覽窗口點擊Game,并且在圖中的位置設(shè)置尺寸,我這里設(shè)置1920 x 1080豎屏,然后把按鈕拖到中間。

這樣我們算是把圖簡單畫好了,接下來我們給控件設(shè)置腳本。我對Unity的開發(fā)不是很了解,但是好像他能為每個對象設(shè)置一個腳本。我們用C#寫一個腳本設(shè)置給上面的Canvas對象,這樣這個對象就能執(zhí)行這個腳本,注意是設(shè)置給最外層的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#也沒關(guān)系,至少寫一個點擊事件還難不倒我們,代碼中腳本名為Test,AndroidJavaClass和AndroidJavaObject是C#和java通訊的類,這兩個類的命名真的是教科書般的命名。

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

獲取到android類是這樣的固定寫法,調(diào)用類中的方法用Call函數(shù),第一個參數(shù)是java那邊定義的方法名,后面的參數(shù)是方法的參數(shù)。

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

這里是獲取到Canvas下的Button對象,然后設(shè)置點擊事件。這里只是簡單的講,有興趣的可以自己去找詳細的API。

代碼寫好之后把腳本添加給Canvas。



點擊1中的Add Component,選著Test腳本,添加后就像2一樣顯示。同樣,如果想移除腳本的話可以右鍵2的地方選著移除。

這樣就把腳本添加成功了。那么現(xiàn)在是怎樣的情況呢?點擊按鈕,就會執(zhí)行腳本中的監(jiān)聽事件,調(diào)用AndroidJavaObject的Call方法,調(diào)用到android中的say方法。

最后,我們需要把android中的內(nèi)容添加到unity中,最后打包的時候才會一起打進去。



如圖一樣,在Assets中創(chuàng)建Plugin文件夾,在創(chuàng)建Android文件夾,下面創(chuàng)建libs和res。



libs中放入wang.jar,就是我們上面打的包,wang.jar里面是不是調(diào)用了android的東西,我這里用的是v4,所以要把一個android的v4包也放進去,不是也用了unity的jar嗎?沒錯,但是這個在打包時會提供,所以這里我們沒必要重復放unity的jar包進去。注意了,不放unity的jar包進去。
res下就放android項目中res下的內(nèi)容。

最后還要把manifest文件放到android文件夾下



這樣就只剩最后的打包了。

三.打包

上邊已經(jīng)把android的內(nèi)容加到unity中了,我們就可以在Unity中打android的apk包了。
還是多說一句,記得要在Edit -》Preferences -》External Tools中設(shè)置SDK路徑


打包方法是點擊File -》 Build Settings



選著player setting,在3中設(shè)置得和項目中的gradle一樣。
可以看出在Build System中選中的是Gradle,所以unity最后會調(diào)用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.

我按照提示找到文件夾,發(fā)現(xiàn)重復的文件是BuildConfig。于是我的做法是把jar包的BuildConfig刪除(先解壓,再刪除,再壓縮)就正常了,合著unity打包的時候還會給你打進去一個BuildConfig。
雖然我能解決了這個問題,但不知道有沒有更好的方法,不然難道每次都要刪除jar包的文件嗎,這樣豈不是很麻煩。

按照上面的操作,我們就能打出一個可以運行的apk文件了,我測試過可以運行,Gif軟件被我刪了,這里就不演示了,不過我們可以反編譯看看unity做處理之后的結(jié)構(gòu)??梢钥闯龆嗔撕芏辔募?/p>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容