zoukankan      html  css  js  c++  java
  • unity游戏框架学习-SDK接入

    概述链接:https://www.cnblogs.com/wang-jin-fu/p/10975660.html

    之前概述有说过SDK的大概功能如下:

    1.账号类:创建、登录、切换

    2.充值

    3.外部分享如微信、朋友圈、FB等

    4.打开外部链接,如论坛、社区、反馈等

    5.功能类:语音、头像、埋点

    这些功能都是sdk提供的,而我们要做的就是调用sdk的接口(ios的OC接口,android的java接口)

    一、android和c#交互

    1.c#调用android方法,如下,使用 AndroidJavaClass获取AndroidJavaObject对象,在通过AndroidJavaObject调用java方法。最常用的是AndroidJavaObject的Call方法,unity文档:http://docs.unity3d.com/ScriptReference/AndroidJavaObject.html
    这个Call是支持多参数的,第一个参数必须是方法名,第二个开始则是各种参数。如果有返回值则需要使用泛型版本Call<Type>。

    using UnityEngine;
    
    /// <summary>
    /// Android帮助库
    /// 提供unity对android端的调用,属性的get和set麻烦封装成方法
    /// </summary>
    public class AndroidHelper
    {
        const string AndroidMainActivity = "com.unity3d.player.UnityPlayer";

    static AndroidJavaObject ms_MainActivity; public static AndroidJavaObject MainActivity { get { if (ms_MainActivity == null) { AndroidJavaClass jc = new AndroidJavaClass (AndroidMainActivity); if (jc != null) { ms_MainActivity = jc.GetStatic<AndroidJavaObject> ("currentActivity"); } } return ms_MainActivity; } } #region MainActivity的非静态方法 public static void Call(string method) { MainActivity.Call(method); } public static void Call(string method, object[] args) { MainActivity.Call(method, args); } public static void Call(string method, bool val) { MainActivity.Call(method, new object[] { val }); } public static void Call(string method, string val) { MainActivity.Call(method, new object[] { val }); } public static string CallWithReturn(string method) { string result = ""; AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); result = jo.Call<string>(method); return result; } #endregion #region MainActivity的静态方法 public static void CallStatic(string method) { MainActivity.CallStatic(method); } public static void CallStatic(string method, string val) { MainActivity.CallStatic(method, new object[] { val }); } public static string CallStaticWithReturn(string val) { string result = ""; AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); result = jo.CallStatic<string>(val); return result; } #endregion }

    2.Java回调unity,public static void UnitySendMessage(String var0, String var1, String var2) ,第一个参数为unity中的一个gameobject名称,第二个参数为这个gameobject身上捆绑的脚本中的一个方法,而第三参数是这个对应方法上的参数

    public static final String UNITY_HANDLER = "SDKMsgHandler";
    **
     * 向Unity传送
    * @param arg1 函数名
    * @param arg2 参数
    */
    public static void UnitySendMessage(String arg1, String arg2)
    {
         UnityPlayer.UnitySendMessage(UNITY_HANDLER, arg1, arg2);
    }

    二、ios和c#的交互,可以参照官网:https://docs.unity3d.com/Manual/PluginsForIOS.html,你需要把你的oc代码放在Plugins/iOS文件夹下才能正确调用到OC的代码

    c#调用ios:c#端

    [DllImport("__Internal")]
    private static extern string U3dGetAvailableDiskSize();
    
    /// <summary>
    /// 获取磁盘空间
    /// </summary>
    public long GetAvailableDiskSize()
    {
        string size = U3dGetAvailableDiskSize();
        return long.Parse(size);
    }

    OC端

    char* _MakeStringCopy( const char* string)
    {
        if (NULL == string) {
            return NULL;
        }
        char* res = (char*)malloc(strlen(string)+1);
        strcpy(res, string);
        return res;
    }
    
    const char* U3dGetAvailableDiskSize()
    {
        struct statfs buf;
        long long freespace = -1;
        if(statfs("/var", &buf) >= 0)
        {
            freespace = (long long)(buf.f_bsize * buf.f_bfree);
        }
        NSString *_msg = [NSString stringWithFormat:@"%lld", freespace];
        
        return _MakeStringCopy([_msg UTF8String]);
    }

    2.OC回调unity:

    UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
    参数1:gameobject名字;参数2:回调函数的名字;参数3:参数。同android开发中java回调c#一样,三个参数都是字符串类型!

    三、好了。我们知道unity跟iosandroid怎么交互了,可以开始设计我们的接口了,首先在c#端,我们需要区分三种平台,iosandroidunity editor三种平台,我们不可能像下面这么写,几十个接口如果都这么写,会原地爆炸的,所以我们需要用的接口来规范我们的代码

    if(platform == ios)
    {
        //xxxx
    }else if(paltform == android)
    {
        //xxxx
    }else if(platform == editor){
        //xxxx
    }

    1.首先我们需要有一个接口类:

    public interface SDKInterface
    {
        /** 登录 **/
        void Login();
    
        /** 打开SDK用户中心界 **/
        void ShowUserCenter();
    }

    2.我们需要有每个平台的具体实现类(其实就是ios调用OC,android调用Java,editor平台啥也不做),如下所示,U3dLoginShowUserCenter是Ios、android两端的实现代码,这里就不上了

    #if UNITY_ANDROID
    public class AndroidSDK : SDKInterface
    {
        /// <summary>
        /// 登录
        /// </summary>
        public void Login()
        {
            Call("U3dLogin");
        }
    
        /// <summary>
        /// 打开SDK用户中心界
        /// </summary>
        public void ShowUserCenter()
        {
            Call("U3dShowUserCenter");
        }
    }
    #endif
    #if UNITY_IOS
    public class IOSSDK : SDKInterface
    {
        [DllImport("__Internal")]
        private static extern void U3dLogin();
    
        [DllImport("__Internal")]
        private static extern void U3dShowUserCenter();
    
        /// <summary>
        /// 登录
        /// </summary>
        public void Login()
        {
            U3dLogin();
        }
    
        /// <summary>
        /// 打开SDK用户中心界
        /// </summary>
        public void ShowUserCenter()
        {
            U3dShowUserCenter();
        }
    }
    #endif
    public class EmptySDK : SDKInterface
    {
        public void Login() { }
    
        public void ShowUserCenter() { }
    }

    3.一个接受两端回调消息的类,iosandroid共用一个就好了,该类会在管理类里面初始化

    public class SDKMsgHandler : MonoBehaviour
    {
        /// <summary>
        /// 登录回调
        /// </summary>
        /// <param name="msg">msg</param>
        public void LoginNotification(string msg)
        {        
        Debug.Log("登录回调:" + msg);
        }
    }

    4.我们需要一个管理类,来确定具体是调用哪一个接口

    public class SDKModule : ModuleBase
    {
        public SDKModule ()
        {
            #if UNITY_EDITOR || GUIDE
            _sdk = new EmptySDK ();
            #elif UNITY_IOS
            _sdk = new IOSSDK();
            #elif UNITY_ANDROID
            _sdk = new AndroidSDK();
            #else
            _sdk = new EmptySDK();
            #endif
    
            GameObject go = new GameObject ("SDKMsgHandler");
            GameObject.DontDestroyOnLoad (go);
            go.AddComponent<SDKMsgHandler> ();
        }
    
        /// <summary>
        /// 登录
        /// </summary>
        public void Login ()
        {
            Debug.Log("Login c");
            _sdk.Login ();
        }
    
        /// <summary>
        /// 打开SDK用户中心界
        /// </summary>
        public void ShowUserCenter ()
        {
            Debug.Log("ShowUserCenter c");
            _sdk.ShowUserCenter ();
        }
    }

    至此,c#端就完成了,然后后两端的代码

    四、android端:android端渠道众多,很有必要跟c#端一样,每个渠道的接口都实现一个自己的实现类,再用具体的SFMainActivity去管理

    android端接sdk有两种方式,两种方式的区别可参考:https://blog.csdn.net/yang8456211/article/details/51356193,个人倾向于使用第二种方式,因为很多系统功能在unity不好实现,但在android端却很好实现,如推送、谷歌支付等

    1.将sdk的代码打成jaraar的包导入到unity.

    android studio(as)导出aar可参考:https://www.jianshu.com/p/b059e84e85d1

    android studio(as)导出jar可参考:https://www.jianshu.com/p/8256c0da444a

    2.将unity导出到android studio,在使用as打apk

       (1)将unity导出的项目,删除其中的src/main文件夹下的assetsjinLibs es三个文件夹,拷贝该工程作为我们的as工程

     (2)新建一个java类SFMainActivity,该类继承自UnityPlayerActivity,该类的职责类似于前面的SDKModule,负责sdk的初始化(例如语言、版本等需要通知渠道方的)和unity接口的封装,前面AndroidSDK即调用的是这个类的方法

        (3)新建一个sdk的接口类,该类和SDKInterface接口一致,新建不同渠道的实现类,实现类继承自接口类,完成具体的sdk功能

        (4)打包的时候只需要把第一步删除的内容拷贝到我们的备份as工程就好了

    五、ios端,ios端相对android端没有这么多渠道,相对会简单一些,我们只需要把OC的代码放在Plugins/iOS文件夹就好了(需要注意OC语法的参数类型转换)

  • 相关阅读:
    JavaScript的数据类型
    伪元素和伪类的区别是什么?
    伪元素::before和::after的详细介绍
    Ksoap2 获取webservice返回值的getResponse() 出现的问题
    解决dropdownlist postback 在 iphone UIwebview 失效的问题
    javascript雪花效果 注释版
    金山词霸每日一句开放平台 .NET demo
    【摘抄】Application.StartupPath和System.Environment.CurrentDirectory的区别
    EditText 监听回车事件 避免2次触发
    【代码】ini 文件读取工具类
  • 原文地址:https://www.cnblogs.com/wang-jin-fu/p/11017653.html
Copyright © 2011-2022 走看看