本文屬于「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#的類
這個類需要掛載在一個場景內存在的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];
}
}
運行效果~
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();
}
運行效果~
三、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", "");
}
}
運行效果~
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();
}
});
}
運行效果~
四、收個尾
以上內容為Unity與iOS、Android之間相互主動調用的所有內容。
如果你不知道如何導出工程,請看一下前幾篇文章
如果你不能理解我的實現步驟,請看一下前幾篇文章
附上我的Unity示例工程,里面包含了上文中所有代碼,打包編譯,進行對應修改應該就能跑~
下載鏈接: https://pan.baidu.com/s/1ge7yRxp 密碼: uppp
關于傳遞參數的實現
由于上面的內容寫得非常詳細,如果結合理論篇的內容完全可以自己實現,我一直在考慮有沒有必要如此喂飯。
這樣吧,大家可以先自己嘗試一下,如果在思考、嘗試之后還是不會,可以在評論中留個言,我會考慮再出一篇傳遞參數的實踐篇~