5、與iOS、Android的交互 實踐篇——主動調用

本文屬于「Unity與iOS、Android平臺的整合」系列文章之一,轉載請注明出處
主要講解Unity與iOS、Android平臺相互主動調用實現

零、前言

由于本文涉及到較多基礎知識,建議讀者們把前面幾篇補完后再往下看

一、前期工作

1.控制臺

Debug.Log();

這個API是我們比較常用的Log輸出工具,但是只能在調試的時候看到,所以我自己寫了個在設備上顯示Log的簡單控制臺,具體制作和使用大家可以在我之后附帶的工程中看到。

using System;
using System.Text;
using UnityEngine;
using UnityEngine.UI;

public class MyConsole : MonoBehaviour
{
    private static MyConsole Instance;
    void Awake() { Instance = this; }
    [SerializeField]
    private Text logTxt;

    private static StringBuilder log = new StringBuilder("這是控制臺:");
    public static void Print(string str)
    {
        log.Append("\n\nTime:");
        log.Append(DateTime.Now.ToString("HH:mm:ss"));
        log.Append("\u3000");
        log.Append(str);
        Instance.logTxt.text = log.ToString();

        Instance.logTxt.rectTransform.anchoredPosition = Vector2.zero;
    }
}
控制臺的編輯器配置
控制的顯示

2.創建一個C#的類

ConnectUnityToiOSAndroid.cs

這個類需要掛載在一個場景內存在的GameObject上,我選擇了攝像機,當然你也可以選擇其他,但是必須要有一個確定的name,這個涉及到iOS、Android主動調用Unity是否成功的問題,不理解的話請仔細看上一篇文章

掛載物體示意圖

為了方便,我會把C#相關的示例代碼都寫在這里。
為了方便,面向Unity開發者的接口我都直接通過編輯器拖拽掛載的方式用按鈕調用。
實際開發中原理都是一樣的,但是不建議像我這樣簡單粗暴地使用~

ConnectUnityToiOSAndroid.cs

using UnityEngine;
public class ConnectUnityToiOSAndroid : MonoBehaviour
{
}

3.創建一個Objective-C的類

這兩個文件需要關聯到Xcode工程中

關聯示意圖

ConnectUnityToiOS.h

#ifndef ConnectUnityToiOS_h
#define ConnectUnityToiOS_h
#endif /* ConnectUnityToiOS_h */
@interface ConnectUnityToiOS:NSObject
@end

ConnectUnityToiOS.mm

#import "ConnectUnityToiOS.h"
@implementation ConnectUnityToiOS
static ConnectUnityToiOS *instance = nil;
+(ConnectUnityToiOS *)sharedInstance{
    @synchronized(self) {
        if(instance == nil) {
            instance = [[[self class] alloc] init];
        }
    }
    return instance;
}
@end
extern "C"{
}

4.創建一個Java的類

這個文件需要關聯到AndroidStudio或Eclipse工程

關聯示意圖

ConnectUnityToAndroid.java

//游戲使用的包名
package com.wsc.ConnectUnityToAndroid;
import android.app.AlertDialog;
import com.unity3d.player.UnityPlayer;
public class ConnectUnityToAndroid {
}

二、Unity主動調用iOS、Android

首先,我們需要設計一個調用需求

現在策劃說:需要一個原生彈窗提示

好的,需求有了,可以開始設計接口了

C#需要向外提供一個接口,供其他C#代碼調用
OC需要提供一個接口,用于調用iOS系統彈窗
Java需要提供一個接口,用于調用Android系統彈窗

0.Unity內部

在ConnectUnityToiOSAndroid.cs中寫兩個方法,寫得很簡單,大家看一下注釋就清楚了

//C#面向Unity開發者的接口
public void ShowNativeTip()
{
    MyConsole.Print("顯示原生彈窗");
    ShowNativeTip_();
}
#if UNITY_EDITOR
//運行在編輯器環境的接口,一般用于編輯器內模擬數據
private void ShowNativeTip_()
{
    MyConsole.Print("這是在Unity環境");
}
#endif

1.Unity -> iOS

在ConnectUnityToiOSAndroid.cs中關聯C++的接口

#if UNITY_IOS
//運行在iOS環境的接口,關聯到C++接口
[DllImport("__Internal")]
private static extern void ShowNativeTip_();
#endif

在ConnectUnityToiOS.mm中用OC寫調用系統彈窗

-(void)ShowNativeTip{
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"這是iOS的原生彈窗"
                                                        message:nil
                                                       delegate:self
                                              cancelButtonTitle:@"確定"
                                              otherButtonTitles:nil];
    [alertView show];
}

在ConnectUnityToiOS.mm中用C++調用OC的接口

extern "C"{
    void ShowNativeTip_(){
        [[ConnectUnityToiOS sharedInstance] ShowNativeTip];
    }
}

運行效果~


iOS下調用原生彈窗運行效果

2.Unity -> Android

在ConnectUnityToiOSAndroid.cs中關聯Java的接口

#if  UNITY_ANDROID
//運行在Android環境的接口
private static void ShowNativeTip_()
{
    //注意,這邊一定要把游戲的包名寫正確,否則找不到類。
    using (AndroidJavaClass jc = new AndroidJavaClass("com.wsc.ConnectUnityToiOSAndroid.ConnectUnityToAndroid"))
    {
        jc.CallStatic("ShowNativeTip_");
    }
}
#endif

在ConnectUnityToAndroid.java中用Java調用系統彈窗

public static void ShowNativeTip_(){
    AlertDialog.Builder builder = new AlertDialog.Builder(UnityPlayer.currentActivity)
            .setMessage("這是Android的原生彈窗")
            .setPositiveButton("確定",null)
    builder.show();
}

運行效果~

Andorid下調用原生彈窗運行效果

三、iOS、Android主動調用Unity

首先,我們又需要設計一個調用需求,誒為什么要說又

現在策劃說:需要獲得原生彈窗關閉的時候時間

好的,需求有了,可以開始設計接口了

C#需要向OC、Java提供一個接口,以接收原生彈窗關閉的通知
OC需要在彈窗關閉時主動調用C#
Java需要在彈窗關閉時主動調用C#

0.Unity

將ConnectUnityToiOSAndroid.cs掛載在某個物體上,我選擇了名為「Camera」的攝像機物體。
在ConnectUnityToiOSAndroid.cs中寫一個方法,寫得很簡單,大家看一下注釋就清楚了

//C#面向iOS、Android的接口
private void NativeTipClosed()
{
    MyConsole.Print("原生彈窗被關閉了");
}

1.iOS -> Unity

在ConnectUnityToiOS.mm中寫OC添加系統彈窗按鈕的監聽

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    if (buttonIndex==0) {
        UnitySendMessage("Camera", "NativeTipClosed", "");
    }
}

運行效果~

iOS下主動調用Unity運行效果

2.Android -> Unity

在ConnectUnityToAndroid.java中寫Java添加系統彈窗按鈕的監聽
由于Java這邊可以直接添加匿名事件,我就不重新分一個函數寫了,以下是和原文的區別示意圖

相對上文添加的內容示意圖
public static void ShowNativeTip_(){
    UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            AlertDialog.Builder builder = new AlertDialog.Builder(UnityPlayer.currentActivity)
                     .setMessage("這是Android的原生彈窗")
                     .setPositiveButton("確定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            UnityPlayer.UnitySendMessage("Camera", "NativeTipClosed", "");
                        }
                    });
            builder.show();
        }
    });
}

運行效果~


Android下主動調用Unity運行效果

四、收個尾

以上內容為Unity與iOS、Android之間相互主動調用的所有內容。
如果你不知道如何導出工程,請看一下前幾篇文章
如果你不能理解我的實現步驟,請看一下前幾篇文章
附上我的Unity示例工程,里面包含了上文中所有代碼,打包編譯,進行對應修改應該就能跑~
下載鏈接: https://pan.baidu.com/s/1ge7yRxp 密碼: uppp

關于傳遞參數的實現

由于上面的內容寫得非常詳細,如果結合理論篇的內容完全可以自己實現,我一直在考慮有沒有必要如此喂飯。
這樣吧,大家可以先自己嘗試一下,如果在思考、嘗試之后還是不會,可以在評論中留個言,我會考慮再出一篇傳遞參數的實踐篇~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容