本文適合的情況如下:
Unity客戶端人員 與 IOS端研發(fā)人員合作的情況
目錄
From U3D to iOS
實(shí)現(xiàn)原理
1.unity工程目錄創(chuàng)建2個(gè)文件?NativeCallProxy.m、NativeCallProxy.h?并且放到Unity工程目錄Plugins/iOS/unity_ios_plus目錄下
2.創(chuàng)建C#調(diào)用腳本?定義對(duì)應(yīng).mm腳本的 調(diào)用接口,調(diào)用也如下
From U3D to iOS
實(shí)現(xiàn)原理
由于U3D無法直接調(diào)用Objc或者Swift語言聲明的接口,幸好U3D的主要語言是C#,因此可以利用C#的特性來訪問C語言所定義的接口,然后再通過C接口再調(diào)用ObjC的代碼(對(duì)于Swift代碼則還需要使用OC橋接)。
下面演示:利用C#的特性來訪問C語言所定義的接口,然后再通過C接口再調(diào)用ObjC的代碼
1.unity工程目錄創(chuàng)建2個(gè)文件?NativeCallProxy.m、NativeCallProxy.h?并且放到Unity工程目錄Plugins/iOS/unity_ios_plus目錄下
?NativeCallProxy.m代碼內(nèi)容:
#import <Foundation/Foundation.h>
#import "NativeCallProxy.h"
//固定寫法
@implementation FrameworkLibAPI
id<NativeCallsProtocol> api = NULL;
+(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi
{
api = aApi;
}
//固定寫法結(jié)束
@end
//固定寫法
extern "C" {
//void showHostMainWindow(const char* color) { return [api showHostMainWindow:[NSString stringWithUTF8String:color]]; };
//返回字符串的1個(gè)函數(shù)
const char* unityCallGetInitData(){
NSString* str=[api unityCallGetInitData];
char* ret = nullptr;
// ret = (char*)malloc([str length]+1);
// memcpy(ret, [str UTF8String], ([str length])+1);
ret = (char*)malloc([str length]);
memcpy(ret, [str UTF8String], [str length]);
return ret;
};
//無返回的1個(gè)函數(shù)
void unityCallJumpLogin(){
return [api unityCallJumpLogin];
};
//無返回、傳入字符串的函數(shù)
void unityCallJumpToRecharge(const char* gameStatus,const char* receOBName,const char* methodName){
return [api unityCallJumpToRecharge:[NSString stringWithUTF8String:gameStatus] :[NSString stringWithUTF8String:receOBName] :[NSString stringWithUTF8String:methodName]];
};
void unityCallCloseVC(){
return [api unityCallCloseVC];
};
//隱私按鈕
void onPrivacyButton(){
return [api onPrivacyButton];
}
//儲(chǔ)值按鈕
const char* storedValue(){
NSString* str=[api storedValue];
char* ret = nullptr;
ret = (char*)malloc([str length]);
memcpy(ret, [str UTF8String], [str length]);
return ret;
}
//切換游戲
const char* ChangeGame(){
NSString* str=[api ChangeGame];
char* ret = nullptr;
ret = (char*)malloc([str length]);
memcpy(ret, [str UTF8String], [str length]);
return ret;
}
}
//extern "C" {
//
//}
NativeCallProxy.h代碼內(nèi)容
// [!] important set UnityFramework in Target Membership for this file
// [!] and set Public header visibility
//固定寫法
#import <Foundation/Foundation.h>
// NativeCallsProtocol defines protocol with methods you want to be called from managed
@protocol NativeCallsProtocol
@required
// other methods 自定義方法
/**
獲取初始json數(shù)據(jù):baseUrl、mac_id、gameType、jwt 【對(duì)應(yīng)mm文件的自定義函數(shù)名】
*/
-(NSString*)unityCallGetInitData;
/**
重新登錄 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
*/
-(void)unityCallJumpLogin;
/**
跳充值頁前保存數(shù)據(jù),充值頁返回后把保存的數(shù)據(jù)發(fā)信息給unity 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
*/
-(void)unityCallJumpToRecharge:(NSString*) gameStatus :(NSString*) receOBName :(NSString*) methodName;
//ios——關(guān)閉vc 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
-(void)unityCallCloseVC;
//隱私按鈕 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
-(void)onPrivacyButton;
//儲(chǔ)值按鈕 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
-(NSString*)storedValue;
//ch Game 【對(duì)應(yīng)mm文件的自定義函數(shù)名的接口】
-(NSString*)ChangeGame;
//自定義方法結(jié)束
@end
//以下為固定寫法
__attribute__ ((visibility("default")))
@interface FrameworkLibAPI : NSObject
// call it any time after UnityFrameworkLoad to set object implementing NativeCallsProtocol methods
+(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi;
@end
勾選iOS平臺(tái)文章來源:http://www.zghlxwxcb.cn/news/detail-740777.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-740777.html
2.創(chuàng)建C#調(diào)用腳本?定義對(duì)應(yīng).mm腳本的 調(diào)用接口,調(diào)用也如下
using System;
using System.Collections;
using System.Collections.Generic;
using LitJson;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using UnityEngine.SceneManagement; //引入 這個(gè)命名空間,讓unity可以使用 Assets/Plugins/iOS 或 Android/ 這里的dll文件
/// <summary>
/// 呼叫安卓或 IOS 工具類
/// </summary>
public class CallAndroidOrIos :MonoBehaviour
{
public static CallAndroidOrIos instance;
private void Awake()
{
instance = this;
}
#region 關(guān)于IOS的操作
/// <summary>
/// 模擬 安卓或iOS ,DLL的類;
/// </summary>
public class NativeAPI
{
#if UNITY_EDITOR || UNITY_ANDROID
/// <summary>
/// 獲取 IOS返回的 json數(shù)據(jù) :baseUrl、mac_id、gameType、jwt
/// </summary>
public static string unityCallGetInitData()
{
return "";
}
/// <summary>
/// 讓IOS 呼叫重新登錄
/// </summary>
/// <returns></returns>
public static void unityCallJumpLogin()
{
Debug.Log("呼叫 ios重新登錄");
}
/// <summary>
/// IOS充值的返回
/// </summary>
public static void unityCallJumpToRecharge(string gameStatus, string
receOBName, string methodName)
{
}
/// <summary>
/// 關(guān)閉當(dāng)前 IOS活動(dòng)頁
/// </summary>
public static void unityCallCloseVC()
{
}
/// <summary>
/// 隱私按鈕
/// </summary>
public static void onPrivacyButton()
{
}
/// <summary>
/// 儲(chǔ)值被點(diǎn)擊
/// </summary>
public static string storedValue()
{
return "";
}
/// <summary>
/// 切換G
/// </summary>
/// <returns></returns>
public static string ChangeGame()
{
return "";
}
#elif UNITY_IOS || UNITY_TVOS
//定義對(duì)應(yīng).mm腳本的 調(diào)用接口-----------
[DllImport("__Internal")]
public static extern string unityCallGetInitData();
[DllImport("__Internal")]
public static extern void unityCallJumpLogin();
[DllImport("__Internal")]
public static extern void unityCallJumpToRecharge(string gameStatus, string
receOBName, string methodName);
[DllImport("__Internal")]
public static extern void unityCallCloseVC();
[DllImport("__Internal")]
public static extern void onPrivacyButton();
[DllImport("__Internal")]
public static extern string storedValue();
[DllImport("__Internal")]
public static extern string ChangeGame();
#endif
}
#endregion
/// <summary>
/// 被安卓調(diào)用過來的 統(tǒng)一函數(shù)名稱 Public void Give_AnCall(string value)
/// </summary>
public const string Give_AnCall = "Give_AnCall";
/// <summary>
/// 當(dāng)處于同一個(gè)物體的時(shí)候;用來區(qū)分函數(shù)名稱
/// </summary>
public const string Give_AnCall2 = "Give_AnCall2";
/// <summary>
/// 關(guān)閉app當(dāng)前頁面
/// </summary>
public void unityCallCloseActivity()
{
if (Application.platform ==RuntimePlatform.IPhonePlayer|| Application.platform==RuntimePlatform.OSXEditor)
{
Debug.Log("IOS 關(guān)閉當(dāng)前Activity----------");
NativeAPI.unityCallCloseVC();//關(guān)閉Ios 活動(dòng)頁
}
else
{
Debug.Log("關(guān)閉當(dāng)前Activity----------");
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能調(diào)用靜態(tài)
AndroidJavaObject s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以調(diào)用非靜態(tài)
s_ActivityContext.Call("unityCallCloseActivity");//關(guān)閉頁面
}
}
/// <summary>
/// 獲取 玩家進(jìn)入哪個(gè)游戲類型 [ 0是推幣機(jī) 1是連連看 -1是未知類型]
/// 并且獲取到 baseURL mac_id jwt gameType
/// </summary>
public IEnumerator unityCallGetInitData(Action<JsonData,string> callBack)
{
int Time = 0;
string strData="";
string Tips="";
try
{
if (Application.platform ==RuntimePlatform.IPhonePlayer)
{
strData = NativeAPI.unityCallGetInitData();
}
else
{
AndroidJavaClass activityClass;
AndroidJavaObject s_ActivityContext;
activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); //只能調(diào)用靜態(tài)
s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity"); //可以調(diào)用非靜態(tài)
strData = s_ActivityContext.Call<string>("unityCallGetInitData");
}
}
catch (Exception e)
{
Tips = "Error:" + e;
if (callBack != null)
{
callBack(null, Tips);
}
//跳出協(xié)程的執(zhí)行
yield break;
}
while (string.IsNullOrEmpty(strData))//等待回調(diào)
{
yield return new WaitForSeconds(1);
Time++;
if (Time >= 10)
{
break; //跳出循環(huán)
}
}
//還是沒有 收到安卓返回?cái)?shù)據(jù)
if (string.IsNullOrEmpty(strData))
{
if (callBack!=null)
{
Tips = "Get the Android Or IOS data timeout";//獲取安卓數(shù)據(jù)超時(shí)
callBack(null, Tips);
}
}
else
{
JsonData jsonData = JsonMapper.ToObject(strData);
if (callBack!=null)
{
callBack(jsonData, "successful");
}
}
}
/// <summary>
/// 跳轉(zhuǎn)到 充值界面 (1.當(dāng)前游戲場(chǎng)景名稱 ,2.物體名稱 ,3.安卓返回參數(shù)到 哪個(gè)函數(shù)接收)
/// </summary>
public void unityCallJumpToRecharge(string ScreenName, string receOBName, string methodName)
{
if (Application.platform ==RuntimePlatform.IPhonePlayer)
{
NativeAPI.unityCallJumpToRecharge(ScreenName,receOBName,methodName);//跳轉(zhuǎn)到 充值
}
else
{
Debug.Log("呼叫 安卓跳轉(zhuǎn)充值!----------------");
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能調(diào)用靜態(tài)
AndroidJavaObject s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以調(diào)用非靜態(tài)
s_ActivityContext.Call("unityCallJumpToRecharge",ScreenName,receOBName,methodName);
}
}
/// <summary>
/// 跳轉(zhuǎn)到 重新登錄界面
/// </summary>
public void unityCallJumpLogin()
{
if (Application.platform ==RuntimePlatform.IPhonePlayer)
{
NativeAPI.unityCallJumpLogin();//IOS 進(jìn)入 重新登錄頁面
}
else
{
Debug.Log("跳轉(zhuǎn)到重新登錄的Activity--------------");
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能調(diào)用靜態(tài)
AndroidJavaObject s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以調(diào)用非靜態(tài)
s_ActivityContext.Call("unityCallJumpLogin");
activityClass = null;
s_ActivityContext = null;
}
}
/// <summary>
/// 顯示UnityLog到 安卓調(diào)試窗
/// </summary>
public void unityCallPrintLog(string log)
{
if (Application.platform ==RuntimePlatform.IPhonePlayer)
{
//TODO
}
else
{
AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能調(diào)用靜態(tài)
AndroidJavaObject s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以調(diào)用非靜態(tài)
s_ActivityContext.Call("unityCallPrintLog",log);
}
}
/// <summary> 打開隱私按鈕 </summary>
public void onPrivacyButton()
{
if (Application.platform ==RuntimePlatform.IPhonePlayer)
{
NativeAPI.onPrivacyButton();
}
else
{
Debug.Log("打開隱私按鈕");
}
}
/// <summary> 打開儲(chǔ)值 </summary>
public void storedValue()
{
if (Application.platform == RuntimePlatform.IPhonePlayer)
{
Debug.Log("ios打開儲(chǔ)值:"+NativeAPI.storedValue());
}
else
{
Debug.Log("打開儲(chǔ)值按鈕");
if (Application.platform == RuntimePlatform.WindowsEditor)
{
//LogoGM.instance.HeroInfo_PlayCount(5);//默認(rèn)給+5個(gè)
//LogoGM.instance.HeroInfoSave();//PC端 增加可玩次數(shù)保存
}
}
}
/// <summary> 查詢是否切換游戲 </summary>
/// <returns></returns>
public string ChangeGame()
{
if (Application.platform == RuntimePlatform.IPhonePlayer)
{
return "IOS查詢是否切換" + NativeAPI.ChangeGame();
}
else
{
return "PC查詢游戲切換";
}
}
/// <summary>
/// IOS調(diào)用Unity的方法:UnitySendMessage("物體名", "函數(shù)名", "回調(diào)字符串");
/// </summary>
/// <param name="msg"></param>
public void ReceIosMsg(string msg)
{
Debug.Log("IOS 回調(diào)的信息");
/*
//根據(jù)游戲的場(chǎng)景劃分 確定回調(diào)邏輯
int scenceId = SceneManager.GetActiveScene().buildIndex;
if (string.IsNullOrEmpty(msg))
{
Debug.Log(scenceId+"場(chǎng)景 收到IOS消息為空字符");
}
else
{
string strType;
string strCode;
//字符串轉(zhuǎn)json對(duì)象
JsonData jsonData = JsonMapper.ToObject(msg);
switch (scenceId)
{
case 0://場(chǎng)景0
try
{
strType = jsonData["type"].ToString();
strCode = jsonData["str"].ToString();
if (strType=="ChuShiHua")
{
int code = int.Parse(strCode);
if (code==0)//非游戲 靜止在這個(gè)界面
{
Debug.Log(scenceId+"場(chǎng)景收到非游戲Code,等待跳轉(zhuǎn)");
//SetOrientationPortrait();//設(shè)置為豎屏
mSpr.gameObject.SetActive(false);
TestUpsideDown(1);
}
else
{
Debug.Log("正常游戲");
toMenu();
}
}
else
{
Debug.Log(scenceId+"場(chǎng)景 收到的不是初始化字段:"+strType);
}
}
catch (Exception e)
{
Debug.LogError(string.Format("{0} 場(chǎng)景 解析數(shù)據(jù)出錯(cuò) 原數(shù)據(jù):{1}",scenceId,msg));
}
break;
case 1://場(chǎng)景1
try
{
strType = jsonData["type"].ToString();
strCode = jsonData["str"].ToString();
if (strType == "APPStore_Scuess")
{
//TODO 儲(chǔ)值成功 添加可玩次數(shù)
Debug.Log("儲(chǔ)值成功");
HeroInfo_PlayCount(9999);
HeroInfoSave();//場(chǎng)景1的儲(chǔ)值
}
else
{
Debug.Log(scenceId+"場(chǎng)景 收到的不是儲(chǔ)值字段:"+strType);
}
}
catch (Exception e)
{
Debug.LogError(string.Format("{0} 場(chǎng)景 解析數(shù)據(jù)出錯(cuò) 原數(shù)據(jù):{1}",scenceId,msg));
}
break;
}
}
*/
}
}
到了這里,關(guān)于Unity3D與iOS的交互 簡(jiǎn)單版開箱即用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!