unity游戏开发之三方SDK接入

出海游戏开发中,sdk接入是必不可少的,sdk接入包括:

1.账号类:创建、登录、切换 Facebook SDK, AppleId SDK

2.充值 ,unity IAP,如果接入其他平台,比如亚马逊,需要调用这些平台的接口

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

4.打开外部链接,如helpshift ,广告平台

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

这些功能都是sdk提供的,而我们要做的就是调用sdk的接口(有的有Unity SDK,有的是原生接口,ios的OC接口,android的java接口)
如果有Unity SDK ,直接导入到Unity 工程,像调用正常的C#方法一样调用即可。

一、android和c#交互

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

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
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身上捆绑的脚本中的一个方法,而第三参数是这个对应方法上的参数

1
2
3
4
5
6
7
8
9
10
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#端

1
2
3
4
5
6
7
8
9
10
11
[DllImport("__Internal")]
private static extern string U3dGetAvailableDiskSize();

/// <summary>
/// 获取磁盘空间
/// </summary>
public long GetAvailableDiskSize()
{
string size = U3dGetAvailableDiskSize();
return long.Parse(size);
}

OC端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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跟ios\android怎么交互了,可以开始设计我们的接口了,首先在c#端,我们需要区分三种平台,ios\android\unity editor三种平台,我们不可能像下面这么写,几十个接口如果都这么写,会原地爆炸的,所以我们需要用的接口来规范我们的代码

1
2
3
4
5
6
7
8
9
if(platform == ios)
{
//xxxx
}else if(paltform == android)
{
//xxxx
}else if(platform == editor){
//xxxx
}

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

1
2
3
4
5
6
7
8
public interface SDKInterface
{
/** 登录 **/
void Login();

/** 打开SDK用户中心界 **/
void ShowUserCenter();
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#if UNITY_ANDROID
public class AndroidSDK : SDKInterface
{
/// <summary>
/// 登录
/// </summary>
public void Login()
{
Call("U3dLogin");
}

/// <summary>
/// 打开SDK用户中心界
/// </summary>
public void ShowUserCenter()
{
Call("U3dShowUserCenter");
}
}
#endif
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
#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
1
2
3
4
5
6
public class EmptySDK : SDKInterface
{
public void Login() { }

public void ShowUserCenter() { }
}

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

1
2
3
4
5
6
7
8
9
10
11
public class SDKMsgHandler : MonoBehaviour
{
/// <summary>
/// 登录回调
/// </summary>
/// <param name="msg">msg</param>
public void LoginNotification(string msg)
{
    Debug.Log("登录回调:" + msg);
}
}

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

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
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#端就完成了。