欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > 内容正文

教你快速高效接入SDK——Unity统一接入渠道SDK(Unity篇),sdkunity

来源: 开发者 投稿于  被查看 23054 次 评论:120

教你快速高效接入SDK——Unity统一接入渠道SDK(Unity篇),sdkunity


上一篇,我们着重讲解了用Unity开发的手游,在接入U8SDK时,Android中的部分。接下来,这一篇,我们就来看看,在Unity工程中,我们需要怎么调用上一篇中我们提供的各种接口,以及怎么接收Android中的消息通知,比如登录成功,切换帐号成功等。

 在写代码之前,我们先要做一个简单的配置,在Project面板中,按照Unity官方的要求,新建一个Plugins文件夹,在Plugins文件夹下,再建立一个Android文件夹。这里,将会放置所有Android工程相关的文件。 1、将上一篇中,我们创建的工程中,将res目录拷贝到该文件夹下2、新建一个bin目录,将Android工程中bin目录下生成的jar拷贝到这里3、新建一个libs目录,将android-support-v*.jar拷贝到这里(注意,之前引入的unity的那个jar不要拷贝过来)4、将U8SDK2抽象层工程中的bin目录下生成的u8sdk2.jar拷贝到libs目录中5、将AndroidManifest.xml拷贝到Android目录下 

完整的结构如下:



这样,整个配置工作就完成了。接下来,我们就来看看,在Unity中怎么来完成Android中相关接口的调用以及封装。 渠道SDK接入,包括Android,IOS,WP等多种平台,这里我们需要抽象出来一个统一的上层接口,供给游戏逻辑层调用,所以我们定义一个U8SDKInterface的抽象单例类:

public abstract class U8SDKInterface{
 
    public delegate void LoginSucHandler(U8LoginResult data);
    public delegate void LogoutHandler();
 
    private static U8SDKInterface _instance;
 
    public LoginSucHandler OnLoginSuc;
    public LogoutHandler OnLogout;
 
 
    public static U8SDKInterface Instance
    {
        get
        {
            if (_instance == null)
            {
#if UNITY_EDITOR || UNITY_STANDLONE
                _instance = new SDKInterfaceDefault();
#elif UNITY_ANDROID
                _instance = new SDKInterfaceAndroid();
#elif UNITY_IOS
                _instance = new SDKInterfaceIOS();
#endif
            }
 
            return _instance;
        }
    }
 
    //初始化
    public abstract void Init();
 
    //登录
    public abstract void Login();
 
    //自定义登录,用于腾讯应用宝,QQ登录,customData="QQ";微信登录,customData="WX"
    public abstract void LoginCustom(string customData);
 
    //切换帐号
    public abstract void SwitchLogin();
 
    //登出
    public abstract bool Logout();
 
    //显示个人中心
    public abstract bool ShowAccountCenter();
 
    //上传游戏数据
    public abstract void SubmitGameData(U8ExtraGameData data);
 
    //调用SDK的退出确认框,返回false,说明SDK不支持退出确认框,游戏需要使用自己的退出确认框
    public abstract bool SDKExit();
 
    //调用SDK支付界面
    public abstract void Pay(U8PayParams data);
 
    //SDK是否支持退出确认框
    public abstract bool IsSupportExit();
 
    //SDK是否支持用户中心
    public abstract bool IsSupportAccountCenter();
 
    //SDK是否支持登出
    public abstract bool IsSupportLogout();
 
    //去U8Server获取游戏订单号,这里逻辑是访问游戏服务器,然后游戏服务器去U8Server获取订单号
    //并返回
    public U8PayParams reqOrder(U8PayParams data)
    {
        //TODO 去游戏服务器获取订单号
 
        //测试
        data.orderID = "345435634534";
        data.extension = "test";
 
        return data;
    }
 
}

有了这个抽象类,对于各个平台,我们需要分别实现该抽象类中的接口,从而间接地调用平台中的方法。对于Android平台,我们定义一个SDKInterfaceAndroid类:
public class SDKInterfaceAndroid : U8SDKInterface
{
 
    private AndroidJavaObject jo;
 
    public SDKInterfaceAndroid()
    {
        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
        {
            jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        }
    }
 
    private T SDKCall<T>(string method, params object[] param)
    {
        try
        {
            return jo.Call<T>(method, param);
        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
        return default(T);
    }
 
    private void SDKCall(string method, params object[] param)
    {
        try
        {
            jo.Call(method, param);
        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
    }
 
    //这里Android中,在onCreate中直接调用了initSDK,所以这里就不用调用了
    public override void Init()
    {
        //SDKCall("initSDK");
         
    }
 
    public override void Login()
    {
        SDKCall("login");
    }
 
    public override void LoginCustom(string customData)
    {
        SDKCall("loginCustom", customData);
    }
 
    public override void SwitchLogin()
    {
        SDKCall("switchLogin");
    }
 
    public override bool Logout()
    {
        if (!IsSupportLogout())
        {
            return false;
        }
 
        SDKCall("logout");
        return true;
    }
 
    public override bool ShowAccountCenter()
    {
        if (!IsSupportAccountCenter())
        {
            return false;
        }
 
        SDKCall("showAccountCenter");
        return true;
    }
 
    public override void SubmitGameData(U8ExtraGameData data)
    {
        string json = encodeGameData(data);
        SDKCall("submitExtraData", json);
    }
 
    public override bool SDKExit()
    {
        if (!IsSupportExit())
        {
            return false;
        }
 
        SDKCall("exit");
        return true;
    }
 
    public override void Pay(U8PayParams data)
    {
        string json = encodePayParams(data);
        SDKCall("pay", json);
    }
 
    public override bool IsSupportExit()
    {
        return SDKCall<bool>("isSupportExit");
    }
 
    public override bool IsSupportAccountCenter()
    {
        return SDKCall<bool>("isSupportAccountCenter");
    }
 
    public override bool IsSupportLogout()
    {
        return SDKCall<bool>("isSupportLogout");
    }
 
    private string encodeGameData(U8ExtraGameData data)
    {
        Dictionary<string, object> map = new Dictionary<string, object>();
        map.Add("dataType", data.dataType);
        map.Add("roleID", data.roleID);
        map.Add("roleName", data.roleName);
        map.Add("roleLevel", data.roleLevel);
        map.Add("serverID", data.serverID);
        map.Add("serverName", data.serverName);
        map.Add("moneyNum", data.moneyNum);
        return MiniJSON.Json.Serialize(map);       
    }
 
    private string encodePayParams(U8PayParams data)
    {
        Dictionary<string, object> map = new Dictionary<string, object>();
        map.Add("productId", data.productId);
        map.Add("productName", data.productName);
        map.Add("productDesc", data.productDesc);
        map.Add("price", data.price);
        map.Add("buyNum", data.buyNum);
        map.Add("coinNum", data.coinNum);
        map.Add("serverId", data.serverId);
        map.Add("serverName", data.serverName);
        map.Add("roleId", data.roleId);
        map.Add("roleName", data.roleName);
        map.Add("roleLevel", data.roleLevel);
        map.Add("vip", data.vip);
        map.Add("orderID", data.orderID);
        map.Add("extension", data.extension);
 
        return MiniJSON.Json.Serialize(map);       
    }
}

首先这个类是继承了之前我们定义的U8SDKInterface抽象类,在所有的接口中,我们都通过SDKCall来间接地调用上一篇中我们定义在U8UnityContext.java中的对应接口。 之前我们说过,和Android中的通信我们采用JSON格式,所以这里你可以看到,在Unity中我们将接口需要的参数,封装成JSON格式传递过去,然后在U8UnityContext中进行解析即可。 PS:后面,等U8SDK支持IOS版本了,我们到时候再来实现SDKInterfaceIOS类。 现在,我们就来看看,游戏逻辑中,怎么调用这些接口吧。正如之前所说的,在需要登录的地方调用:U8SDKInterface.Instance.Login();需要支付的地方调用:U8SDKInterface.Instance.Pay(U8PayParams data);其他接口类似 现在部分接口调用之后,我们是希望有回调的。比如调用Login接口之后,我们就只有等待登录结果。这个是个异步的过程。所以,我们怎么在Unity来接收Android的回调通知呢? 为了能够在Unity中接收到平台的回调通知,我们需要定义一个常驻内存的GameObject,然后在GameObject身上绑定一个负责通知回调的脚本,在脚本中定义一系列回调的函数。 还记得,在上一篇中,我们在U8UnityContext中,定义了一个一系列常量,包括如下:      public final static String CALLBACK_GAMEOBJECT_NAME = “(u8sdk_callback)”;     
     public final static String CALLBACK_INIT = “OnInitSuc”;                              
     public final static String CALLBACK_LOGIN = “OnLoginSuc”;                         
     public final static String CALLBACK_SWITCH_LOGIN = “OnSwitchLogin”;               
     public final static String CALLBACK_LOGOUT = “OnLogout”;                              public final static String CALLBACK_PAY = “OnPaySuc”;                            其中,CALLBACK_GAMEOBJECT_NAME就是Unity中这个负责接收回调通知的GameObject的名称,而下面几个就是回调脚本中需要定义的函数的函数名称。 所以,接下来,我们就定义一个专门负责回调的脚本:
public class U8SDKCallback : MonoBehaviour
{
 
    private static U8SDKCallback _instance;
 
    private static object _lock = new object();
 
    //初始化回调对象
    public static U8SDKCallback InitCallback()
    {
        UnityEngine.Debug.LogError("Callback->InitCallback");
 
        lock (_lock)
        {
            if (_instance == null)
            {
                GameObject callback = GameObject.Find("(u8sdk_callback)");
                if (callback == null)
                {
                    callback = new GameObject("(u8sdk_callback)");
                    UnityEngine.Object.DontDestroyOnLoad(_instance);
                    _instance = callback.AddComponent<U8SDKCallback>();
 
                }
                else
                {
                    _instance = callback.GetComponent<U8SDKCallback>();
                }
            }
 
            return _instance;
        }
    }
 
 
    //初始化成功回调
    public void OnInitSuc()
    {
        //一般不需要处理
        UnityEngine.Debug.LogError("Callback->OnInitSuc");
    }
 
    //登录成功回调
    public void OnLoginSuc(string jsonData)
    {
        UnityEngine.Debug.LogError("Callback->OnLoginSuc");
 
        U8LoginResult data = parseLoginResult(jsonData);
        if (data == null)
        {
            UnityEngine.Debug.LogError("The data parse error." + jsonData);
            return;
        }
 
        if (U8SDKInterface.Instance.OnLoginSuc != null)
        {
            U8SDKInterface.Instance.OnLoginSuc.Invoke(data);
        }
    }
 
    //切换帐号回调
    public void OnSwitchLogin()
    {
 
        UnityEngine.Debug.LogError("Callback->OnSwitchLogin");
 
        if (U8SDKInterface.Instance.OnLogout != null)
        {
            U8SDKInterface.Instance.OnLogout.Invoke();
        }
    }
 
    //登出回调
    public void OnLogout()
    {
        UnityEngine.Debug.LogError("Callback->OnLogout");
 
        if (U8SDKInterface.Instance.OnLogout != null)
        {
            U8SDKInterface.Instance.OnLogout.Invoke();
        }
    }
 
    //支付回调,网游不需要实现该接口,该接口用于单机游戏
    public void OnPaySuc(string jsonData)
    {
        //Nothing...
    }
 
    private U8LoginResult parseLoginResult(string str)
    {
        object jsonParsed = MiniJSON.Json.Deserialize(str);
        if (jsonParsed != null)
        {
            Dictionary<string, object> jsonMap = jsonParsed as Dictionary<string, object>;
            U8LoginResult data = new U8LoginResult();
            if (jsonMap.ContainsKey("isSuc"))
            {
                data.isSuc = bool.Parse(jsonMap["isSuc"].ToString());
            }
            if (jsonMap.ContainsKey("isSwitchAccount"))
            {
                data.isSwitchAccount = bool.Parse(jsonMap["isSwitchAccount"].ToString());
            }
            if (jsonMap.ContainsKey("userID"))
            {
                data.userID = jsonMap["userID"].ToString();
            }
            if (jsonMap.ContainsKey("sdkUserID"))
            {
                data.sdkUserID = jsonMap["sdkUserID"].ToString();
 
            }
            if (jsonMap.ContainsKey("username"))
            {
                data.username = jsonMap["username"].ToString();
            }
 
            if (jsonMap.ContainsKey("sdkUsername"))
            {
                data.sdkUsername = jsonMap["sdkUsername"].ToString();
            }
            if (jsonMap.ContainsKey("token"))
            {
                data.token = jsonMap["token"].ToString();
            }
 
            return data;
        }
 
        return null;
    }
}

在游戏运行的最开始的时候,记得调用U8SDKCallback.InitCallback来进行初始化,自动创建一个负责回调的GameObject,同时将该脚本绑定到这个对象上。 到这里,U8SDK在Unity中的封装基本就算完成了,接下来,我们就来测试下接口的调用。我们用UGUI建立一个建立一个简单的面板,然后包含一个登录按钮和支付按钮,然后通过绑定一个ClickObject.cs脚本来简体按钮的响应事件:
public class ClickObject : MonoBehaviour {
 
    // Use this for initialization
 
    private Text txtState;
 
    void Start () {
 
        U8SDKCallback.InitCallback();
 
        GameObject loginObj = GameObject.Find("BtnLogin");
        Button btnLogin = loginObj.GetComponent<Button>();
        btnLogin.onClick.AddListener(delegate()
        {
            OnLoginClick();
        });
 
        GameObject payObj = GameObject.Find("BtnPay");
        Button btnPay = payObj.GetComponent<Button>();
        btnPay.onClick.AddListener(delegate()
        {
            OnPayClick();
        });
 
        GameObject stateObj = GameObject.Find("TxtState");
        txtState = stateObj.GetComponent<Text>();
         
 
        U8SDKInterface.Instance.OnLoginSuc = delegate(U8LoginResult result)
        {
            OnLoginSuc(result);
        };
 
        U8SDKInterface.Instance.OnLogout = delegate()
        {
            OnLogout();
        };
    }
 
    void Update()
    {
        if (Input.GetKeyUp(KeyCode.Escape))
        {
            if (!U8SDKInterface.Instance.SDKExit())
            {
                //TODO 退出确认框
                Application.Quit();
            }
        }
    }
 
 
    void OnLoginSuc(U8LoginResult result)
    {
        if (!result.isSuc)
        {
            txtState.text = "登录失败";
            return;
        }
 
        if (result.isSwitchAccount)
        {
            txtState.text = "切换帐号成功:" + result.token;
        }
        else
        {
            txtState.text = "登录成功:" + result.token;
        }
 
 
    }
 
    void OnLogout()
    {
        txtState.text = "未登录";
    }
 
    void OnLoginClick()
    {
        U8SDKInterface.Instance.Login();
    }
 
    void OnPayClick()
    {
        U8PayParams data = new U8PayParams();
        data.productId = "1";
        data.productName = "元宝";
        data.productDesc = "购买100元宝,赠送20元宝";
        data.price = 100;
        data.buyNum = 1;
        data.coinNum = 300;
        data.serverId = "10";
        data.serverName = "地狱之恋";
        data.roleId = "u8_24532452";
        data.roleName = "麻利麻利吼";
        data.roleLevel = 15;
        data.vip = "v15";
         
        data = U8SDKInterface.Instance.reqOrder(data);
 
        U8SDKInterface.Instance.Pay(data);
    }
 
 
}

好了,到这里,我们已经演示了,如何在Unity开发的手游中,完成U8SDK接口的调用和封装。完整的demo演示可以点击这里下载:HERE

好了,如果你对U8SDK感兴趣,欢迎访问U8SDK的官方网站深入了解哦。(HERE)


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关频道:

用户评论