U8SDK——Unity手游接入U8SDK(Unity篇)
上一篇,我们着重讲解了用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的抽象单例类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
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类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
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中,定义了一个一系列常量,包括如下:
1 2 3 |
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的名称,而下面几个就是回调脚本中需要定义的函数的函数名称。
所以,接下来,我们就定义一个专门负责回调的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
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脚本来简体按钮的响应事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
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技术博客,转载时请注明出处及相应链接。
本文永久链接: http://www.uustory.com/?p=1866