Unity3D与iOS的交互 简单版开箱即用

这篇具有很好参考价值的文章主要介绍了Unity3D与iOS的交互 简单版开箱即用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文适合的情况如下:

Unity客户端人员 与 IOS端研发人员合作的情况

目录

From U3D to iOS

实现原理

1.unity工程目录创建2个文件 NativeCallProxy.m、NativeCallProxy.h 并且放到Unity工程目录Plugins/iOS/unity_ios_plus目录下

2.创建C#调用脚本 定义对应.mm脚本的 调用接口,调用也如下


From U3D to iOS

实现原理

由于U3D无法直接调用Objc或者Swift语言声明的接口,幸好U3D的主要语言是C#,因此可以利用C#的特性来访问C语言所定义的接口,然后再通过C接口再调用ObjC的代码(对于Swift代码则还需要使用OC桥接)。

下面演示:利用C#的特性来访问C语言所定义的接口,然后再通过C接口再调用ObjC的代码

1.unity工程目录创建2个文件 NativeCallProxy.m、NativeCallProxy.h 并且放到Unity工程目录Plugins/iOS/unity_ios_plus目录下

Unity3D与iOS的交互 简单版开箱即用,Unity,iOS,ios,unity

 NativeCallProxy.m代码内容:

#import <Foundation/Foundation.h>
#import "NativeCallProxy.h"

//固定写法
@implementation FrameworkLibAPI

id<NativeCallsProtocol> api = NULL;
+(void) registerAPIforNativeCalls:(id<NativeCallsProtocol>) aApi
{
    api = aApi;
}
//固定写法结束
@end

//固定写法
extern "C" {
//void showHostMainWindow(const char* color) { return [api showHostMainWindow:[NSString stringWithUTF8String:color]]; };


//返回字符串的1个函数
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个函数
void unityCallJumpLogin(){
  return  [api unityCallJumpLogin];
};

//无返回、传入字符串的函数
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];
}

//儲值按鈕
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代码内容

// [!] 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数据:baseUrl、mac_id、gameType、jwt 【对应mm文件的自定义函数名】
 */
-(NSString*)unityCallGetInitData;
/**
 重新登录	【对应mm文件的自定义函数名的接口】
 */
-(void)unityCallJumpLogin;
/**
 跳充值页前保存数据,充值页返回后把保存的数据发信息给unity 【对应mm文件的自定义函数名的接口】
 */
-(void)unityCallJumpToRecharge:(NSString*) gameStatus :(NSString*) receOBName :(NSString*) methodName;

//ios——关闭vc 【对应mm文件的自定义函数名的接口】
-(void)unityCallCloseVC;

//隱私按鈕 【对应mm文件的自定义函数名的接口】
-(void)onPrivacyButton;

//储值按钮 【对应mm文件的自定义函数名的接口】
-(NSString*)storedValue;

//ch Game 【对应mm文件的自定义函数名的接口】
-(NSString*)ChangeGame;

//自定义方法结束
@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平台

Unity3D与iOS的交互 简单版开箱即用,Unity,iOS,ios,unity文章来源地址https://www.toymoban.com/news/detail-740777.html

2.创建C#调用脚本 定义对应.mm脚本的 调用接口,调用也如下

using System;
using System.Collections;
using System.Collections.Generic;
using LitJson;
using UnityEngine;
using UnityEngine.UI;
using System.Runtime.InteropServices;
using UnityEngine.SceneManagement; //引入  这个命名空间,让unity可以使用 Assets/Plugins/iOS 或 Android/ 这里的dll文件

/// <summary>
/// 呼叫安卓或 IOS 工具类
/// </summary>
public class CallAndroidOrIos :MonoBehaviour
{

    public static CallAndroidOrIos instance;
    private void Awake()
    {
        instance = this;
    }

    #region  关于IOS的操作

    
 /// <summary>
 /// 模拟 安卓或iOS ,DLL的类;
 /// </summary>
    public class NativeAPI
   {
       
#if UNITY_EDITOR || UNITY_ANDROID

       /// <summary>
       /// 获取 IOS返回的 json数据 :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>
       /// 关闭当前 IOS活动页
       /// </summary>
       public static  void unityCallCloseVC()
       {
           
       }

       /// <summary>
       /// 隐私按钮
       /// </summary>
       public static void onPrivacyButton()
       {
           
           
       }

       /// <summary>
       /// 储值被点击
       /// </summary>
       public static string storedValue()
       {
           return "";
       }
     
       /// <summary>
       /// 切换G
       /// </summary>
       /// <returns></returns>
       public static string ChangeGame()
       {
           return "";
       }

    
     
  
#elif UNITY_IOS || UNITY_TVOS 

       //定义对应.mm脚本的 调用接口-----------
       [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>
    /// 被安卓调用过来的 统一函数名称  Public void Give_AnCall(string value)
    /// </summary>
    public const string Give_AnCall = "Give_AnCall";

    /// <summary>
    /// 当处于同一个物体的时候;用来区分函数名称
    /// </summary>
    public const string Give_AnCall2 = "Give_AnCall2";
    
    /// <summary>
    /// 关闭app当前页面
    /// </summary>
    public void unityCallCloseActivity()
    {

        if (Application.platform ==RuntimePlatform.IPhonePlayer|| Application.platform==RuntimePlatform.OSXEditor)
        {
            Debug.Log("IOS 关闭当前Activity----------");
            NativeAPI.unityCallCloseVC();//关闭Ios 活动页
        }
        else
        {
            Debug.Log("关闭当前Activity----------");
            AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能调用静态
            AndroidJavaObject  s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以调用非静态
            s_ActivityContext.Call("unityCallCloseActivity");//关闭页面 
        }
        
     
    }



    /// <summary>
    /// 获取 玩家进入哪个游戏类型 [ 0是推币机 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"); //只能调用静态
                s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity"); //可以调用非静态
                strData = s_ActivityContext.Call<string>("unityCallGetInitData");
            }

        }
        catch (Exception e)
        {
            Tips = "Error:" + e;
            if (callBack != null)
            {
                callBack(null, Tips);
            }
 
            //跳出协程的执行
            yield break;
        }
        
        while (string.IsNullOrEmpty(strData))//等待回调
        {
            yield return new WaitForSeconds(1);
            Time++;
            if (Time >= 10)
            {
                break; //跳出循环
            }
        }

        //还是没有 收到安卓返回数据  
        if (string.IsNullOrEmpty(strData))
        {
             
            if (callBack!=null)
            {
                Tips = "Get the Android Or IOS data timeout";//获取安卓数据超时
                callBack(null, Tips);
            } 
        }
        else
        {
            JsonData jsonData = JsonMapper.ToObject(strData);
            if (callBack!=null)
            {
                callBack(jsonData, "successful"); 
            }
        }
        
    }




    /// <summary>
    /// 跳转到 充值界面 (1.当前游戏场景名称 ,2.物体名称 ,3.安卓返回参数到 哪个函数接收) 
    /// </summary> 
    public void unityCallJumpToRecharge(string ScreenName, string receOBName, string methodName)
    {

        if (Application.platform ==RuntimePlatform.IPhonePlayer)
        {
            NativeAPI.unityCallJumpToRecharge(ScreenName,receOBName,methodName);//跳转到 充值
        }
        else
        {
            Debug.Log("呼叫 安卓跳转充值!----------------");
            AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能调用静态
            AndroidJavaObject  s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以调用非静态
            s_ActivityContext.Call("unityCallJumpToRecharge",ScreenName,receOBName,methodName); 
        }
     
    }



    /// <summary>
    /// 跳转到 重新登录界面
    /// </summary>
    public void unityCallJumpLogin()
    {
        if (Application.platform ==RuntimePlatform.IPhonePlayer)
        {
            NativeAPI.unityCallJumpLogin();//IOS 进入 重新登录页面
        }
        else
        {
            Debug.Log("跳转到重新登录的Activity--------------");
            AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能调用静态
            AndroidJavaObject  s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以调用非静态
            s_ActivityContext.Call("unityCallJumpLogin");
            activityClass = null;
            s_ActivityContext = null;
        }
    }



    /// <summary>
    /// 显示UnityLog到 安卓调试窗
    /// </summary>
    public void unityCallPrintLog(string log)
    {
        if (Application.platform ==RuntimePlatform.IPhonePlayer)
        {
            //TODO 
        }
        else
        {
            AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");//只能调用静态
            AndroidJavaObject  s_ActivityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");//可以调用非静态
            s_ActivityContext.Call("unityCallPrintLog",log);
        }
        
     
 
    }


    /// <summary> 打开隐私按钮 </summary>
    public void onPrivacyButton()
    {

        if (Application.platform ==RuntimePlatform.IPhonePlayer)
        {
            NativeAPI.onPrivacyButton();
        }
        else
        {
            Debug.Log("打开隐私按钮");
        }
    }

    /// <summary> 打开储值 </summary>
    public void storedValue()
    {
        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
           Debug.Log("ios打开储值:"+NativeAPI.storedValue()); 
        }
        else
        {
            Debug.Log("打开储值按钮");
            if (Application.platform == RuntimePlatform.WindowsEditor)
            {
                //LogoGM.instance.HeroInfo_PlayCount(5);//默认给+5个
                //LogoGM.instance.HeroInfoSave();//PC端 增加可玩次数保存
                
            }
        }
    }

    /// <summary> 查询是否切换游戏 </summary>
    /// <returns></returns>
    public string ChangeGame()
    {
        if (Application.platform == RuntimePlatform.IPhonePlayer)
        {
            return "IOS查询是否切换" + NativeAPI.ChangeGame();
        }
        else
        {
            return "PC查询游戏切换";
        }
    }
    
    
    
    
    /// <summary>
    /// IOS调用Unity的方法:UnitySendMessage("物体名", "函数名", "回调字符串");
    /// </summary>
    /// <param name="msg"></param>
    public void ReceIosMsg(string msg)
    {
        Debug.Log("IOS 回调的信息");
        
        /*
        //根据游戏的场景划分 确定回调逻辑
        int scenceId = SceneManager.GetActiveScene().buildIndex;
        if (string.IsNullOrEmpty(msg))
        {
            Debug.Log(scenceId+"场景 收到IOS消息为空字符");
        }
        else
        {
            string strType;
            string strCode;
            //字符串转json对象
            JsonData jsonData = JsonMapper.ToObject(msg);
            switch (scenceId)
            {
                case 0://场景0
				
                    try
                    {
                        strType = jsonData["type"].ToString();
                        strCode = jsonData["str"].ToString();
                        if (strType=="ChuShiHua")
                        {
                            int code = int.Parse(strCode);
                            if (code==0)//非游戏 静止在这个界面
                            {
                                Debug.Log(scenceId+"场景收到非游戏Code,等待跳转");
                                //SetOrientationPortrait();//设置为竖屏
                                mSpr.gameObject.SetActive(false);
                                TestUpsideDown(1);
								 
							 
                            }
                            else
                            {
                                Debug.Log("正常游戏");
                                toMenu();
                            }
                        }
                        else
                        {
                            Debug.Log(scenceId+"场景 收到的不是初始化字段:"+strType);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(string.Format("{0} 场景 解析数据出错 原数据:{1}",scenceId,msg));
                    }
                    break;
                case 1://场景1
                    try
                    {
                        strType = jsonData["type"].ToString();
                        strCode = jsonData["str"].ToString();
                        if (strType == "APPStore_Scuess")
                        {
                            //TODO 储值成功 添加可玩次数
                            Debug.Log("储值成功");
                            HeroInfo_PlayCount(9999);
                            HeroInfoSave();//场景1的储值
                        }
                        else
                        {
                            Debug.Log(scenceId+"场景 收到的不是储值字段:"+strType);
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogError(string.Format("{0} 场景 解析数据出错 原数据:{1}",scenceId,msg));
                    }
                    break;
            }
        }
	    */
        
		
    }
}

到了这里,关于Unity3D与iOS的交互 简单版开箱即用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity3D开发之unity和js通信交互

    官方 方法分享:Unity - 手动:与浏览器脚本的交互 (unity3d.com) 首先需要写一个JS的脚本,主要是调用mergeInto();方法,第一个参数不用变,第二个参数就是JS的方法集合。写完之后将这个文件的后缀改为.jslib,放到Plugins文件夹中  Test  内容: 2.C#(挂在场景 任意物体上) 3.Uni

    2024年02月12日
    浏览(43)
  • Unity3D2020+导出Android工程中使用并交互

    , 目录 1,版本信息 2,前期准备 Unity方面: Android方面: 3,Android与Unity3D交互 unity2020+ android studio 2021 *不要用android studio 2020系列,存在不能导入Library的bug 1,先配置打包的一些必要要素,包括包名之类 2,修改打包选项,将其打包为Android工程  3,打包出来的工程如下,其中

    2023年04月08日
    浏览(64)
  • 【Unity3D】程序纹理简单应用

            本文所有案例的完整资源详见→Unity3D程序纹理简单应用。 1.1 边框          1)边框子图         Border.shadersubgraph         说明:Any 节点用于判断输入向量中是否存在一个分量非零,Branch 节点根据输入的真假走不同的分支,详见→Shader Graph节点。       

    2024年02月12日
    浏览(39)
  • Unity3D Pico VR 手势识别物体交互 适配 MRTK3

     当前Pico已经支持手势识别了,但是提供的PICO Unity Integration SDK 中是没有手势和物体交互的功能,Unity XR Interaction Toolkit提供的手势识别物体交互对 Quest适配的挺好的,Pico 当前只能用指尖点触还不能对物体进行抓握以及手势控制射线对物体进行交互。 如要项目想要使用Pico 手

    2024年01月21日
    浏览(61)
  • 【Unity3D】如何在uniyt中切换画布实现切换界面的交互操作

    我们在切换不同界面的时候,时常会用到切换场景的操作。 如果在一个场景里就可以去实现切换界面的时候,若再使用切换场景来实现,会占用很大的空间,不妨在一个场景里使用切换画布的方法来实现切换界面的交互操作。  效果如图所示:  在第一个画布中,点击按钮后

    2024年02月12日
    浏览(47)
  • Unity3d 制作一个简单的NPC对话系统

    ​ 最近在自己写一个比较小的项目,虽然自己是一个策划,但是程序方面我觉得也是很有必要学一学的。 ​ 经过了接近一年的学习,也终于是可以独自写一些小的系统了。 ​ 这次自己写了一个比较简单的NPC对话系统,供大家参考。 进入对话区域 开始对话 Inspector面板可调

    2023年04月08日
    浏览(47)
  • Unity3d(webGL)构建数字孪生小案例(包含完整的数据交互体系)附赠完整代码

    B站视频演示 点击获取合视频对应的完整版代码 项目文档 数字孪生demo项目,打通了,模型-硬件终端-webGL-web端-服务端的数据交互,属于较为完整的项目练习。 包含文件:unity工程文件;webGL文件;前后端代码文件;硬件代码; 先来看看概念吧: 数字孪生体是现有或将有的物

    2024年02月09日
    浏览(58)
  • 【unity3D】unity记忆翻牌小游戏教程(简单详细)

    游戏开发的 学习记录 ⑨ (最近在做得游戏里想加一个类似于记忆翻牌小游戏得部分,然后在网上收集了资料学习了一下,学会后写下这份制作记录,希望可以帮到你~) 📜一位大佬的博客,写的很详细:【Unity3D游戏教程】记忆翻牌游戏 (大家可以先看大佬这篇,我写这篇

    2024年02月07日
    浏览(283)
  • Unity3D教程:触发器实现简单的场景跳转

    首先,需确保有一个想要跳转的目标场景。在本案例中,目标场景是ending。 第一步:创建一个碰撞体,放置在需要的触发场景跳转的位置。 第二步:删除多余的脚本,并且新建自己的脚本: 第三

    2024年02月12日
    浏览(56)
  • 【Unity3d】 教会你如何做一个简单的电梯系统(升降平台)

           博主第一次写博客,语言略俗,有不足之处还请指正!        由于自己还处在unity小白阶段,受2d升降平台的影响(后续我也会上传关于2d升降平台的文章),突发奇想如何用3d做一个电梯系统,查阅网上资料后,发现网上对这方面的讲解少之又少,或者说其他博主提

    2024年02月11日
    浏览(121)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包