# PC SDK Unity对接指南
# 介绍
独立游戏的STOVE平台提供包括游戏发行及销售、社区、指标分析等在内的游戏上市所有过程一站式处理综合服务。 使用PC SDK(Unity,以下简称PC SDK)可以轻松将Stove平台提供的服务整合到游戏中。
这里说明连接PC SDK的方法。
如果是第一次对接PC SDK,请先阅读PC SDK Unity示例。
# 事前准备
- 确认是否在STOVE Studio (opens new window)上获得了加入STOVE的账户和游戏上线用Appkey、App secret、Game Id。
- 建议设置Unity 2017以上和Visual Studio 2017以上版本。
- 在PC SDK 下载页面上下载最新版本的
Unity(C#)
分发文件(以下标记为StovePCSDK_NET
)。
# StovePCSDK_NET发行文件配置
# 1) StovePCSDK 文件夹
下载并解压缩STovePCSDK_NET,StovePCSDK
文件夹包含以下文件夹。
Plugins
Unity Project插件文件夹。
Plugins\x86
包含x86平台所需的二进制文件。
Plugins\x86_64
x64平台所需的二进制文件。
# StovePCSDK_NET 构建环境
# 1) 添加 Assets
打开要合并的Unity项目,保留上述StovePCSDK
文件夹内x86x86_64文件夹中的一个,并删除另一文件夹,然后复制 "StovePCSDK` 文件夹并将其粘贴到Assets文件夹的下游。
# 2) 检查x86文件夹中的文件
选择x86文件夹下方的文件,并检查Inspector的Platform settings部分是否勾选了 Windows x86条目。如果未选中,请选择复选框。
# 3) 检查x86_64文件夹中的文件
选择x86_64文件夹下方的文件,并检查Inspector的Platform settings部分是否勾选了Windows x86_x64条目。如果未选中,请选择复选框。
# #### 4) Build Settings
单击File > Build Settings...菜单,打开 Build Settings对话框,点击Player Settings...按钮,打开Inspector或Project Settings窗口。
Other Settings组 > Configuration领域 > Api Compatibility Level项目设置如下:
Unity 2018以前版本:.NET 2.0(不是.NET 2.0 Subset)
Unity 2018以后版本:.NET 4.x(不是.NET Standard 2.0)
# 5) 创建空游戏目标
在适当的场景中创建GameObject -> Create Empty。为了方便起见,名称设置为 StovePCSDKManager。
# 6) 添加脚本组件
将Script组件添加到StovePCSDKManager Object。
为了方便起见,脚本的名称设置为StovePCSDKManager
。
# 7) 创建脚本
在Awake方法中执行以下处理,以便StovePCSDKManager Object不会因场景切换等因素解除。
private void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
2
3
4
# 对接PC SDK
# 1) RunCallback
PC SDK的API为了不妨碍游戏引擎及游戏逻辑,大部分都是异步执行。 API呼叫的结果将装载在PC SDK内部的队列上,游戏想要处理API呼叫的结果时,通过呼叫RunCallback方法进行相应回拨。 一般情况下RunCallback方法的呼叫使用Corutin编写,呼叫周期可以设置。
private IEnumerator RunCallback(float intervalSeconds)
{
WaitForSeconds wfs = new WaitForSeconds(intervalSeconds);
while (true)
{
StovePC.RunCallback();
yield return wfs;
}
}
2
3
4
5
6
7
8
9
Corutin通过MonoBehaviour.StartCoroutine
方法开始,一般是PC SDK初始化
成功后启动,PCSDK退出成功后停止。
PC SDK退出成功后,为了终止RunCallback Corutin,可使用成员变量方法。
private Coroutine runcallbackCoroutine;
游戏项目中的成员变量 runcallback Coroutine
,可如下面的代码所示,使用StartCoroutine
函数和StopCoroutine
函数,使它们像定时器一样工作。
public void ToggleRunCallback_ValueChanged(bool isOn)
{
if (isOn)
{
float intervalSeconds = 1f;
runcallbackCoroutine = StartCoroutine(RunCallback(intervalSeconds));
WriteLog("RunCallback Start");
}
else
{
if (runcallbackCoroutine != null)
{
StopCoroutine(runcallbackCoroutine);
runcallbackCoroutine = null;
WriteLog("RunCallback Stop");
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 2) Config, Callback配置
为了初始化PC SDK,首先为填写StovePCConfig
和StovePCCallback
结构体,然后调用 StovePC.Initialize
方法。
参考以下代码填充StovePCConfig
结构体的每个字段值。
StovePCConfig config = new StovePCConfig
{
Env = "live",
AppKey = "YOUR_APP_KEY",
AppSecret = "YOUR_SECRET_KEY",
GameId = "YOUR_GAME_ID",
LogLevel = StovePCLogLevel.Debug,
LogPath = ""
};
2
3
4
5
6
7
8
9
"YOUR_APP_KEY", "YOUR_SECRET_KEY", "YOUR_GAME_ID"必须填写
STOVE Studio
发放的密钥值。 未登录STOVE客户端调用stovePC.Initialize
方法时会报错,请提前运行STOVE客户端并登录。
游戏和PC SDK之间的对接使用C# Delegate。
游戏需要定义以下StovePCCallback
Class回拨相关的Deligate方法:
public class StovePCCallback
{
// StovePCSDK 发生错误时调用回拨
public StovePCErrorDelegate OnError;
// PC SDK 初始化完成后呼叫的回拨
public StovePCInitializationCompleteDelegate OnInitializationComplete;
// GetToken 处理完成时调用回拨
public StovePCTokenDelegate OnToken;
// GetUser 处理完成时调用回拨
public StovePCUserDelegate OnUser;
// GetOwnership 处理完成时调用回拨
public StovePCOwnershipDelegate OnOwnership;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
此处需要注意的是,StovePCCallback
客体应保存到PCSDK结束为止。其理由是StovePCCallback
客体一旦进行Gavage collecting,PC SDK内部就无法呼叫回拨。
为了满足这一点,StovePCCallback
class 可以被宣布为游戏项目class的成员变量,从而避免Gavage收集。
private StovePCCallback callback;
// 创建 StovePCCallback 类 instance
this.callback = new StovePCCallback
{
OnError = new StovePCErrorDelegate(this.OnError),
OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
OnToken = new StovePCTokenDelegate(this.OnToken),
OnUser = new StovePCUserDelegate(this.OnUser),
OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership)
};
2
3
4
5
6
7
8
9
除必须对接的"OnError"、"OnInitialization Complete"、"OnOwnership"回调函数,其余回调函数可在必要时进行对接。例如,仅使用所有权(Ownership)功能时,可使用如下连接Deligate方法。
/*
仅使用所有权(Ownership)功能时,
除了必须实现的回拨OnError、OnInitialization Complete之外
对接OnOwnership呼叫。
*/
this.callback = new StovePCCallback
{
OnError = new StovePCErrorDelegate(this.OnError),
OnInitializationComplete = new StovePCInitializationCompleteDelegate(this.OnInitializationComplete),
OnOwnership = new StovePCOwnershipDelegate(this.OnOwnership)
};
2
3
4
5
6
7
8
9
10
11
# 3) SDK 初始化
调用StovePC.Initialize
方法来初始化PC SDK。
StovePCResult sdkResult = StovePC.Initialize(config, this.callback);
if (StovePCResult.NoError == sdkResult)
{
this.runCallbackCoroutine = StartCoroutine(RunCallback(0.5f));
// 没有初始化错误,故循环调用RunCallback
}
else
{
// 初始化失败,终止游戏
}
2
3
4
5
6
7
8
9
10
StovePC.Initialize
方法在确认config和callback有效性后,立即返回StovePCResult
enum 类型值。
如果成功,则返回StovePCResult.NoError
值。失败时,应返还相应错误代码,并终止游戏。
返回值为StovePCResult.NoError
,即成功时,定期调用StovePC. RunCallback
方法。
只有定期调用StovePC. RunCallback
方法,连接的回拨才会正常调用。
如果呼叫周期长,回拨的响应速度也会变慢,因此最好保持适当的呼叫周期。示例代码中设定为每秒调用一次回传函数。
用Initialize方法初始化PC SDK的线程(Thread) 和`StovePC.RunCallback' 方法调用返回函数的线程必须相同。
"StovePC.Initialize方法除确认config和callback有效性外,其它操作均以异步处理。 异步操作成功时,调用
OnInitialization Complete回拨;发生错误时,调用
OnError回拨。 发生错误时,可通过传送的
StovePCError`结构体确认错误代码、信息等。
private void OnInitializationComplete()
{
Debug.Log("PC SDK initialization success");
}
private void OnError(StovePCError error)
{
#region Log
StringBuilder sb = new StringBuilder();
sb.AppendLine("OnError");
sb.AppendFormat(" - error.FunctionType : {0}" + Environment.NewLine, error.FunctionType.ToString());
sb.AppendFormat(" - error.Result : {0}" + Environment.NewLine, (int)error.Result);
sb.AppendFormat(" - error.Message : {0}" + Environment.NewLine, error.Message);
sb.AppendFormat(" - error.ExternalError : {0}", error.ExternalError.ToString());
WriteLog(sb.ToString());
#endregion
switch (error.FunctionType)
{
case StovePCFunctionType.Initialize:
case StovePCFunctionType.GetUser:
case StovePCFunctionType.GetOwnership:
BeginQuitAppDueToError();
break;
}
}
private void BeginQuitAppDueToError()
{
#region Log
StringBuilder sb = new StringBuilder();
sb.AppendLine("BeginQuitAppDueToError");
sb.AppendFormat(" - nothing");
WriteLog(sb.ToString());
#endregion
// 或许,与其说您立即中断应用程序,不如向用户展示关于中断应用程序的信息后,
// 根据用户动作(e.g.点击结束按钮)可能想要中断应用程序。
// 那么,请在此删除 QuitApplication ,以实现您的专属逻辑。
// 关于建议的必要事前作业错误的信息如下。
// 韩语:필수 사전 작업이 실패하여 게임을 종료합니다.
// 其它语言 : The required pre-task fails and exits the game.
QuitApplication();
}
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
如果需要在 OnInitialisationComplete 回调之前查找 PC SDK 的初始化状态值,可以使用 StovePC.GetInitialisationState 函数。
// 调用 StovePC.Initialize 之后...
while (StovePC.GetInitializationState() == StovePCInitializationState.Pending)
{
Thread.Sleep(500);
StovePC.RunCallback();
}
if (StovePC.GetInitializationState() == StovePCInitializationState.Complete)
{
// 초기화 완료 OnInitializationComplete 콜백이 호출됨
}
else
{
// 초기화 실패 OnError 콜백이 호출됨
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如果需要在 OnInitialisationComplete 回调之前查找 PC SDK 的初始化状态值,可以使用 StovePC.GetInitialisationState 函数。
// 调用 StovePC.Initialize 之后...
while (StovePC.GetInitializationState() == StovePCInitializationState.Pending)
{
Thread.Sleep(500);
StovePC.RunCallback();
}
if (StovePC.GetInitializationState() == StovePCInitializationState.Complete)
{
// 初始化完成 OnInitialisationComplete 回调被调用
}
else
{
// 初始化完成 OnInitialisationComplete 回调被调用
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 4) 对接SDK时的注意事项
在初始化完成之前调用
GetToken
,GetUser
,GetOwnership
方法可能无法正常获得结果。也就是说,在正常接收到OnInitialization Complete
回拨后,必须调用"GetToken"、"GetUser"、"GetOwnership"方法才能正常收到结果。
StovePCCConfig 结构体设置日志级别时,PC SDK测试时请输入
StovePCLogLevel.Debug
值,正式构建时请设置StovePCLogLevel.Eror
值,防止产生不必要的日志。
# 5) SDK 退出
结束PC SDK使用后通过呼叫整理使用中的资源。调用StovePC.Uninitialize
方法后,PC SDK 的API将停止工作。在调用StovePC.Uninitialize
方法之前或之后,必须通过StopCoroutine
函数停止runcallbackCoroutine
的Coroutine运行。
StovePCResult result = StovePC.Uninitialize();
if (result == StovePCResult.NoError)
{
// 成功处理
}
2
3
4
5
# 6) 获取用户信息
您可以使用StovePC.GetUser
方法查看登录到STOVE客户端 (opens new window)的用户信息。
StovePCResult result = StovePC.GetUser();
if (result == StovePCResult.NoError)
{
// 成功处理
}
2
3
4
5
正常处理StovePC.GetUser
方法后,调用OnUser
回拨。
通过Callback上传达的StovePCUser
结构体,可以了解用户的成员号码、昵称、游戏用户ID信息。
private void OnUser(StovePCUser user)
{
// 输出用户信息
StringBuilder sb = new StringBuilder();
sb.AppendLine("OnUser");
sb.AppendFormat(" - user.MemberNo : {0}" + Environment.NewLine, user.MemberNo.ToString());
sb.AppendFormat(" - user.Nickname : {0}" + Environment.NewLine, user.Nickname);
sb.AppendFormat(" - user.GameUserId : {0}", user.GameUserId);
Debug.Log(sb.ToString());
}
2
3
4
5
6
7
8
9
10
11
# 7) 获取令牌信息
获取使用StovePC.GetToken
方法登录到STOVE客户端的用户的令牌信息。
StovePCResult result = StovePC.GetToken();
if (result == StovePCResult.NoError)
{
// 成功处理
}
2
3
4
5
如果正常处理了StovePC.GetToken
方法,则调用OnToken
回拨
传递到回拨的StovePCToken
结构包含令牌字符串。
private void OnToken(StovePCToken token)
{
// 令牌信息输出
StringBuilder sb = new StringBuilder();
sb.AppendLine("OnToken");
sb.AppendFormat(" - token.AccessToken : {0}", token.AccessToken);
Debug.Log(sb.ToString());
}
2
3
4
5
6
7
8
9
令牌是什么? 通过登录STOVE Launcher的用户的Access Token,游戏服务器可以将该Access Token传达给Stove认证服务器,进行登录用户的有效性验证。 有关Access Token的详细说明,请咨询store.support@smilegate.com获得技术支援。
# 8) 获取所有权信息
使用StovePC.GetOwnership
方法查询登录STOVE客户端的用户是否购买并拥有该游戏。
StovePCResult result = StovePC.GetOwnership();
if (result == StovePCResult.NoError)
{
// 成功处理
}
2
3
4
5
如果正常处理了StovePC.GetOwnership
方法,则调用OnOwnership
回拨。
下面是OnOwnership
回拨中判断是否购买游戏的示例代码。
没有DLC的游戏时,不需要22~27行的确认代码。
private void OnOwnership(StovePCOwnership[] ownerships)
{
bool owned = false;
foreach(var ownership in ownerships)
{
// [LOGIN_USER_MEMBER_NO] StovePCUser 构造体的 MemberNo
// [Ownership Code] 1:取得所有权,2:所有权解除(取消购买时)
if (ownership.MemberNo != LOGIN_USER_MEMBER_NO ||
ownership.OwnershipCode != 1)
{
continue;
}
// [GameCode] 3: BASIC 游戏, 4: DEMO
if (ownership.GameId == "YOUR_GAME_ID" &&
ownership.GameCode == 3)
{
设置为 owned = true; // 所有权确认变量设为true
}
// 只有销售DLC的游戏时才需要
if (ownership.GameId == "YOUR_DLC_ID" &&
ownership.GameCode == 5)
{
// 因为拥有YOUR_DLC_ID(DLC)所有权,所以允许使用DLC
}
}
if(owned)
{
// 所有权验证正常完成后创建进入游戏的logic
}
else
{
// 所有权验证失败后终止游戏,进行错误信息显示逻辑
}
}
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
- 用购买游戏的账户(拥有所有权)登录STOVE客户端后即可正常游戏。
- 用没有游戏所有权的账号登录STOVE客户端后,运行exe时显示以下提示信息(示例)后终止游戏。
- 韩语以外的操作系统 : Please log in to STOVE Client with the account that has purchased the game.
- 韩语:게임을 구매한 계정으로 STOVE 클라이언트에 로그인하시기 바랍니다.
即使没有拥有游戏所有权的账号,也可以测试所有权功能,详细方法请确认FAQ。
- 另外,调用所有权( Ownership) <GetOwnership Success> 后,请在 output_log.txt 或 Player.log 中添加以下日志:
示例 :
成功: 拥有所有权的用户。
失败: 没有所有权的用户。
2
3
4
- 日志文件激活指南: [https://docs.unity3d.com/530/Documentation/Manual/LogFiles.html] (https://docs.unity3d.com/530/Documentation/Manual/LogFiles.html)
# 确认错误
PC SDK使用过程中发生的错误大致可分为两种情况。
# 调用方法后返回的 StovePCResultenum 值
PC SDK 的全部方法将在调用后立即返回StovePCResult
enum 值,表示调用是否成功。
返回的错误代码可在PCSDK 错误代码 页面上查看。
# 通过 OnError 回拨传递的 StovePCError 结构
PC SDK API 发生错误时,将会调用OnError
回拨,传递包含错误详细信息的StovePCError
结构体。
// OnError 回拨将在调用时传递。
public struct StovePCError
{
// 显示调用函数的 enum 值
public StovePCFunctionType FunctionType;
// 显示错误类型的 enum 值
public StovePCResult Result;
// 发生错误消息
public string Message;
// 外部错误(http 错误,外部模块错误)发生时,相应的错误代码
public int ExternalError;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15