【Unity3d】Unity与iOS之间通信

这篇具有很好参考价值的文章主要介绍了【Unity3d】Unity与iOS之间通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在Unity开发或者SDK开发经常遇到Unity与移动端原生层之间进行通信,这里把它们之间通信做一个整理。

关于Unity与Android之间通信,参考【Unity3d】Unity与Android之间通信

Unity调用Objective-C

主要分三个步骤:

(一)、在xcode中定义要被unity调用的函数

新建一个类,名字可以任意,比如UnityBridge:

头文件:UnityBridge.h (头文件中不需要字段和函数声明)

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface UnityBridge : NSObject

@end

NS_ASSUME_NONNULL_END

头文件里没什么代码,主要代码在实现文件中。

实现文件:UnityBridge.m

实现文件中需要用c语言定义函数,这些函数定义了之后,就可以被unity调用:

#import "UnityBridge.h"

//如果c#调用oc函数时需要一个回调,需要先声明回调参数类型:
typedef void (*MyResultCallback) (int status,const char *result);

//在.m文件中以下4行可以不需要
#if defined (__cplusplus)
extern "C"
{
#endif

	//这里写被unity调用的函数
	
 	void test1(void){
		//这里是函数实现,支持oc语法
	}

	/**
	* int类型参数,返回int
	*/
	int test2(int params){
		//这里是函数实现,支持oc语法
	}
	/**
	* 字符串类型参数
	*/
	void test3(const char *params){
		//这里是函数实现,支持oc语法
	}

	/**
	* 返回字符串时,不能直接返回oc转c的字符串,要调用strdup函数再返回
	*/
	const char* test4(void){
		//返回字符串时,需要使用c分配内存再返回,否则闪退
		//return "abc" //错误,会闪退
		//return [@"abc" UTF8String];//错误,会闪退
		//return strdup("abc") //正确	
		
		//strdup函数需要引入#import <string.h>
		return strdup([@"abc" UTF8String]) //要调用strdup()函数分配c内存再返回给unity,不然闪退
	}

	/**
	* 支持回调参数
	*/
	void test5(MyResultCallback callback){
		//这里是函数实现,支持oc语法
		int code = 0;
		NSString p = @"test";
		const char *result = [p UTF8String];
		//回调给c#
		callback(code,result)
	}
	
//在.m文件中以下3行可以不需要
#if defined (__cplusplus)
}
#endif

函数返回类型是字符串时,oc这边不能直接返回oc转c的char*字符,否则闪退,c++闪退代码行:

// Marshaling cleanup of return value native representation
il2cpp_codegen_marshal_free(returnValue);
原因是oc使用了ARC自动释放内存,c层再去free内存发现未分配就会报错。
需要调用strdup()函数再返回,函数所在头文件:#import <string.h> 参见上面示例代码的test4()函数。

注意这些代码不要写在@implementation中,它是c语言的函数。

C++支持函数重载,而C不支持,两者的编译规则也不一样。函数被C++编译后在符号库中的名字与C语言的不同。例如,假设某个函数的原型为: void foo( int x, int y ); 该函数被C编译器编译后在符号库中的名字可能为_foo,而C++编译器则会产生像_foo_int_int之类的名字(不同的编译器可能生成的名字不 同,但是都采用了相同的机制,生成的新名字称为“mangled name”)。_foo_int_int这样的名字包含了函数名、函数参数数量及类型信息,C++就是靠这种机制来实现函数重载的。如果要在C++中使用C的函数,需要加extern "C"修饰。
#if defined (__cplusplus) 这是一个宏判断,c++中才有这个宏。extern "C"也是c++的关键字。因为oc是支持c++(在.mm文件中才支持),extern "C"表示后面函数是c语言的,供外部调用的。如果在.m文件中,可以不需要extren “C”。

(二)、将oc代码复制到unity工程中。

将oc代码(包括.h和.m源文件)拷贝到Unity工程的Assets目录或子目录中。

实际上将oc代码放在unity工程的Assets目录下的任意位置都可以,oc代码会自动被unity引擎识别。

(笔者使用的unity版本是2019.4,以前的版本不知道是否可以是任意位置。)

为了方便管理,oc代码一般放在Assets/Plugins/iOS中。

也可以将代码打包成framework静态库,然后将其拷贝到unity工程的Assets目录中,一般放在 Assets/Plugins/iOS这个目录中。Unity导出xcode会自动依赖这个framework。

(三)、在unity的c#脚本中声明外部(oc)函数原型
using System.Runtime.InteropServices; //需要引入这个命名空间,会提示引入
using UnityEngine;

public class Test

{
   
    private Test() {}


  
#if UNITY_IOS //加个宏比较好

	//以下是外部函数声明,函数签名必须与oc函数保持一致,参数类型用各自语言的,类型映射见文末。
	//声明无参数无返回值的函数
    [DllImport("__Internal")]
    private static extern void test1();
    
	//声明有一个int参数和int返回值的函数
 	[DllImport("__Internal")]
    private static extern int test2(int p);
    
	//声明一个string参数的函数
    [DllImport("__Internal")]
    private static extern void test3(string p);

	//声明返回string类型的函数
    [DllImport("__Internal")]
    private static extern string test4();

	//如果需要oc的回调,声明一个回调函数类型
    delegate void MyResultDelegate(int code,string result);
    
    [DllImport("__Internal")]
    private static extern void test5(MyResultDelegate resultDelegate);
    
	/**
	* 回调函数的实现(或者叫实例)
	*  注意:必须是static类型的
	*/
   	[AOT.MonoPInvokeCallback(typeof(MyResultDelegate))]
     private static void MyResultDelegateInstance(int code, string result)
     {
       //这里写接收到oc回调的代码
     }

#endif

 	 public  void CallOC()
	  {
	  #if UNITY_IOS
	  	test1();
	  	int result1 = test2(1);
	  	test3("abc");
	  	string result2 = test4();
	  	test5(MyResultDelegateInstance);
	  #endif
      }
}

在c#中调用oc中对应的方法,参见以上 CallOC()

c#调用oc注意事项:

1、数据类型需要使用各自语言的,两者数据类型映射关系在文未。

2、c#中声明的oc方法、回调,都需要static修饰。

Objective-C调用Unity(c#)

oc调用c#比较简单,一般使用以下这个方法:

  UnitySendMessage("MyTestObject", "TestFunc", "msg");

UnitySendMessage函数声明在UnityFramework.frameworkUnityInterface.h头文件中:

void  UnitySendMessage(const char* obj, const char* method, const char* msg);

第一个参数obj表示unity中物体GameObject的名字,注意不是c#脚本的名称也不是类名。

如下图:
unity 自动生成objective-c,Unity3D,iOS,unity,ios
第二个参数method表示这个物体挂载的c#脚本中方法的名字。

第三个参数表示msg表示这个方法接收的数据。

例如,以上物体MyTestObject挂载了MyScript.c#脚本(如上图),MyScript.c#中有TestFunc方法:

using UnityEngine;

public class MyScript : MonoBehaviour
{

    private void TestFunc(string content)
 	{
 		//这里是接收oc调用的实现
	}  
             
}

那么在oc中调用UnitySendMessage("MyTestObject", "TestFunc", "msg") c#的TestFunc方法就会执行。

如果有多个参数需要发送,推荐使用json格式。

oc调用c#注意事项:

1、需要依赖UnityFramework.framework框架。

2、unity工程导出的xcode工程默认已经有UnityFramework.framework

3、如果是自己新建的xcode工程需要手动导入这个框架。

附:c#与oc数据类型映射:文章来源地址https://www.toymoban.com/news/detail-789074.html

Unity(c#) Objective-C
int int
float float
bool bool
string const char *
long long long

到了这里,关于【Unity3d】Unity与iOS之间通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • vue项目接入unity3D模块并进行数据通信

    unity工程师会提供一个前端可使用的包,将其放在vue项目的 public 下,我这里以 unity 文件夹命名

    2024年02月01日
    浏览(46)
  • Unity3D WebGL平台使用WebSocket通信的方法和示例

          之前在WebGL平台和服务端交互的时候使用的是UnityWebRequest,通过WebAPI的方式进行交互,后来发现可以用WebSocket交互后就果断换了WebSocket。 一、Unity3D客户端 我在Unity端使用的是 NativeWebSocket NativeWebSocket下载地址 直接导入Unity即可, 下面是适配的代码,直接挂载在GameObject。

    2024年02月11日
    浏览(48)
  • Unity3d使用Netcode实现Hololens、Android和Pc端通信

    在Unity3d中使用现有的Netcode/Mirror组件实现Hololens、Android和Pc端的三方通信,可以指定一平台为服务器端,其他的两平台多为客户端,不过通常是进行两个平台的通信即可。在这片文章中,可以实现平移、缩放以及旋转的同步 具体步骤如下: 版本:unity2020.3LTS、VS2019 一、配置

    2024年02月09日
    浏览(52)
  • 【Unity3D日常开发】Unity3D中协程的使用

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 最近有小伙伴问协程怎么用、怎么写,我也是会用会写,但是原理不是很明白。 学习了一下,总结出

    2024年02月12日
    浏览(59)
  • unity3D基础操作之01--unity3d窗口界面介绍

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 1、Scene场景编辑窗口; 2、Game游戏运行窗口; 3、Hierarchy场景物体列表窗口; 4、Project项目资源列表窗口; 5、Inspector属性编辑列表窗口; 6、其他常调节窗口 在屏幕左上方为场景编辑窗口Scene,在场景编

    2024年02月06日
    浏览(80)
  • 【Unity3D】Unity3D 软件安装 ( 注册账号并下载 Unity Hub | 安装 Unity Hub | 获取个人版授权 | 中文环境设置 | 安装 Unity3D 编辑器 )

    Unity 官方网站 : 英文 : https://unity.com 中文 : https://unity.cn 进入 中文网站 https://unity.cn , 点击右上角的 \\\" 下载 Unity \\\" 按钮 ; 推荐下载 Unity3D 的长期支持版本 ; 点击界面中的 \\\" 下载 Unity Hub \\\" 选项 ; 根据你的系统 , 选择对应的 Unity Hub , 我在 Windows 上开发 , 因此选择 \\\" Windows 下载 \\\"

    2024年01月25日
    浏览(101)
  • 【Unity3D小功能】Unity3D中实现Text显示版本功能

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 在项目开发中,会遇到要控制版本的情况,比如说对比版本号,版本不对再更新版本的功能,这些就是

    2024年02月05日
    浏览(77)
  • 【Unity3D日常开发】Unity3D中实现单例模式详解

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 我的个人博客 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 首先,说一下,什么是 单例模式(Singleton) 。 单例模式是设计模式中常见的一种设计模式,目的是为了

    2024年02月02日
    浏览(65)
  • 【Unity3D-01】 记录Unity3D调用外接摄像头

    最近想在Unity3D上调用一个摄像头,通过查找资料发现仙魁XAN和八哥快走开的博客符合我的想法,实现起来也不难就尝试了一下 2.1 在这个工程里新建Canvas 如下图所示 然后下设RawImage为载体 2.2 在Assets里面新建一个脚本命名为PlaneManager.cs 代码内容如下(参考八哥快走开的博客)

    2024年02月04日
    浏览(54)
  • 【Unity3D小功能】Unity3D中实现点击‘文字’出现‘UI面板’

    推荐阅读 CSDN主页 GitHub开源地址 Unity3D插件分享 简书地址 QQ群:398291828 大家好,我是佛系工程师 ☆恬静的小魔龙☆ ,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 宠粉博主又来了,今天有粉丝问我如何实现点击一段文字然后出现的面板在那段文字附近显示: 深入了

    2024年04月13日
    浏览(83)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包