Unity和IOS相互通信方式、生成unitypage包

前言

本内容讲解IOS、Unity项目通信的方式,以及IOS如何生成一个unitypager包,供Unity安装使用。

Demo: https://github.com/LSnumber1/UnityAndIOSMessageDemo

Unity调用IOS方法

  1. 创建一个Xcode工程

    依次点击File->New->Project

    选择 Cocoa Touch Static Libray
    在这里插入图片描述

    如果选择的Cocoa Touch Framework创建库也是可以的,本案例是演示静态库的创建,所以,如果选择了Cocoa Touch Framework 记得Mach-O Type属性设置为"Static Library"

    如下:
    在这里插入图片描述

  2. 创建一个本地类,提供要暴露的方法

    创建的本地类,起名为:StudentStaticLibrary.h

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface StudentStaticLibrary : NSObject
    
    - (void) showMessage: (NSString *) content;
    
    @end
    

    实现为:

    #import "StudentStaticLibrary.h"
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @implementation StudentStaticLibrary
    
    - (void)showMessage:(NSString *)content {
        NSLog(@"Unity 传过来的参数为:%@",content);
    }
    
    @end
    

    在此,我们构建了一个有参的函数,当unity调用后,会打印unity传递过来的数据。

  3. 创建桥接文件,供unity调用

    桥接文件起名为:Bridge.h

    #ifndef Bridge_h
    #define Bridge_h
    
    + (Bridge *)sharedInstance;
    
    @end
    #endif /* Bridge_h */
    

    实现为:Bridge.mm

    #import <Foundation/Foundation.h>
    #import "StudentStaticLibrary.h"
    #import "Bridge.h"
    
    @implementation Bridge
    
      //提供几个单例调用
    + (Bridge *)sharedInstance {
        static dispatch_once_t oneceToken;
        dispatch_once(&oneceToken, ^{
            object = [[Bridge alloc] init];
        });
    
        return object;
    }
    //下面定义的是C语言的代码,因为通信机制就是用C语言做的桥接
    #if defined (__cplusplus)
    extern "C" {
    #endif
      
      // 获取StudentStaticLibrary对象的实例,调用方法,StudentStaticLibrary可以设置为单例模式,或者作为成员变量,避免每次创建实例。
        void _showMessage(char* content){
            NSLog(@"mm文件响应了");
            StudentStaticLibrary *library = [[StudentStaticLibrary alloc] init];
            NSString *string = [[NSString alloc] initWithUTF8String:content];
            [library showMessage: string];
        }
    #if defined (__cplusplus)
    }
    #endif
    
    @end
    
  4. 把头文件暴露出来

    ![image-20190331104234978](/Users/ls/Library/Application Support/typora-user-images/image-20190331104234978.png)

    至此,IOS需要写的代码,就是这些,接下来是unity端的代码。

  5. 创建一个UnityToIOS.cs

    此方法为Unity调用IOS的中介。

     public static class UnityToIOS
        {
            [DllImport("__Internal")]
            private static extern void _showMessage(string str);
    
            public static void ShowMeeage()
            {
                _showMessage("调动IOS方法");
            }
        }
    

    DllImport声明的方法名称,要和 IOS中的方法名字完全一样,即"extern “C” "中声明的方法名字。

  6. 创建测试类进行测试

    TestForIOS.cs

    public class TestForIOS : MonoBehaviour
    {
        // Start is called before the first frame update
        void Start()
        {
            #if UNITY_IPHONE
            UnityToIOS.ShowMeeage();
            #endif
        }
    
        // Update is called once per frame
        void Update()
        {
        }
    }
    

至此Unity调用IOS的步骤完成。

IOS调用Unity方法

IOS调用Unity的方法,通过UnitySendMessage方法实现。

  1. 在桥接文件中,声明一个UnitySendMessage方法

    此类和上边介绍Unity调用IOS方法的类是同一个,所以这边为了简略,只写核心方法了。

    Bridge.mm

    #if defined (__cplusplus)
    extern "C" {
    #endif
    
     void UnitySendMessage( const char * className, const char * methodName, const char * param );
     
      //此处,发送消息给Unity
       char *_lableName(char *str){
         //第一个参数为gameobject的名字,第二个为捆绑在gameobject的方法,第三个为参数
            UnitySendMessage("Main Camera","unityGet", str);
            return MakeStringCopy(str);
        }
      
    	char *MakeStringCopy(const char *string) {
            if (NULL == string) {
                return NULL;
            }
            char *res = (char *)malloc(strlen(string) + 1);
            strcpy(res, string);
            return res;
        }
      
    #if defined (__cplusplus)
    }
    #endif
    
    1. Unity端对应的gameobject上有一个接受方法
    public class TestForIOS : MonoBehaviour
    {
      
        // Start is called before the first frame update
        void Start()
        {
         
        }
    
        // Update is called once per frame
        void Update()
        {
        }
    		
    		//ios 发送消息,unity端接受的方法。
        public void unityGet(string s)
        {
            
        }
    }
    

回调方法的使用

存在一种需求,如果类调用了某个方法后,希望把结果通知桥接文件中,我们可以用回调的方法操作。

  1. 声明Deleaget

    StudentStaticLibrary.h

    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    /**
     * @protocol  FAT_Delegate
     * @brief   SDK接口回调协议
     */
    @protocol FAT_Delegate <NSObject>
    @required
    
    - (void)fat_CallBack:(id)response;
    
    @end
    
    @interface StudentStaticLibrary : NSObject
    //属性,接口
    @property (nonatomic, assign) id <FAT_Delegate>delegate;
    - (void) showMessage: (NSString *) content;
    
    @end
    
    
    

    StudentStaticLibrary.m

    #import "StudentStaticLibrary.h"
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @implementation StudentStaticLibrary
    
    - (void)showMessage:(NSString *)content {
        NSLog(@"Unity 传过来的参数为:%@",content);
      	//收到消息后,处理回调
        if ([[self delegate] respondsToSelector:@selector(fat_CallBack:)]) {
            [[self delegate] fat_CallBack:@"回调"];
        }
    }
    
    @end
    
    
  2. 在桥接文件中,实现回调

    Bridge.h

    #ifndef Bridge_h
    #define Bridge_h
    //实现接口
    @interface Bridge : NSObject <FAT_Delegate>
    + (Bridge *)sharedInstance;
    
    @end
    #endif /* Bridge_h */
    

    Bridge.mm

    #import <Foundation/Foundation.h>
    #import "StudentStaticLibrary.h"
    #import "Bridge.h"
    
    //保存回调
    static id object;
    
    @implementation Bridge
    
    + (Bridge *)sharedInstance {
        static dispatch_once_t oneceToken;
        dispatch_once(&oneceToken, ^{
            object = [[Bridge alloc] init];
        });
    
        return object;
    }
    
    //实现回调
    - (void)fat_CallBack:(id)response {
        NSLog(@"callback: %@",response);
    }
    
    //设置回到
    - (void)setLinstener{
        object = self;
    }
    
    @end
    
    
    #if defined (__cplusplus)
    extern "C" {
    #endif
        
        static Bridge *bridge;
        
        void UnitySendMessage( const char * className, const char * methodName, const char * param );
    
        void _showMessage(char* content){
           
            NSLog(@"mm文件响应了");
            if(bridge==NULL)
            {
                bridge = [Bridge sharedInstance];
            }
          	//设置回调
            [bridge setLinstener]; 
            
            StudentStaticLibrary *library = [[StudentStaticLibrary alloc] init];
          	//赋值
            library.delegate = object;
            NSString *string = [[NSString alloc] initWithUTF8String:content];
            [library showMessage: string];
        
        }
        
    #if defined (__cplusplus)
    }
    #endif
    
    

打unitypage包

考虑一种场景,采用上述产生的IOS包,Unity开发人员无法直接使用,需要写桥接文件去对应相应的方法,增加工作量,所以我们想有没有办法生成一个包,unity可以直接调用,不需要关系桥接文件等,只需要像我们在IOS中调用三方库一样的方便。

答案就是生成一个unitypage包,我们在编写完成IOS的包后,在unity端实现一个cube,cube中我们写好通信的方法,然后,提供一个单例供unity调用即可。

  1. 把所需的类都放在一个文件夹下

    包括prefab文件、cs文件、ios的包、头文件等。

  2. 导出unitypage
    在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值