需求
使用 Unity 引擎为游戏接入 steam 渠道,上架 steam 平台。需要接入 steam 登录和支付功能。
登录功能:https://partner.steamgames.com/doc/features/auth
应用内购买功能:https://partner.steamgames.com/doc/features/microtransactions/implementation
实现
根据 steam 文档 商用引擎和非 C++ 语言支持 ,steam sdk 不支持 unity 原生端,需要使用第三方插件 Steamworks.NET。
-
安装 Steamworks.NET ,推荐使用 方式 A 安装。安装完成后,项目的 Assets/ 文件下会增加
com.rlabrecque.steamworks.net
文件夹,和 Script/Steamworks.NET 下有SteamManager
文件。项目的根目录还会自动生成一个 steam_appid.txt 文件(注意这个文件不能删除)。 -
修改 steam_appid.txt 文件里的 AppId(480)修改成你项目的 AppId。
-
找到 SteamManager 文件下的
SteamAPI.RestartAppIfNecessary(AppId_t.Invalid)
打开 AppId_t 类,替换 Invalid 的属性,使用你项目的 AppId .
-
重启 Unity 使 steam_appid.txt 文件生效。
-
经过以上步骤,steamworks 安装成功。
-
根据 Getting Started with Steamworks.NET 初始化 Steamworks 。具体操作如下:
- 将 SteamManager.cs 挂在项目第一个场景上,这个场景不会被销毁的。
- 创建一个实现 steam 的脚本,将这个脚本也挂在 项目的第一个场景上。
- 在
Start()
生命周期方法中发送获取登录票证的方法:SteamUser.GetAuthTicketForWebApi(mSteamID.ToString());
- 在
OnEnable()
生命周期方法中注册监听票据的回调。 - 在回调中获取到 steam 返回的票据发送到您的服务器验证。
由于 steam 文档不是特别清晰,可以参考 steamworks 的示例代码:https://github.com/rlabrecque/Steamworks.NET-Test
代码如下:
public class SteamScript : MonoBehaviour
{
private const string Tag = "[SteamScript]";
//每次激活或停用 Steam Overlay 时,它都会向您发送回调。
protected Callback<GameOverlayActivated_t> m_GameOverlayActivated;
// 等待票据验证
protected Callback<GetTicketForWebApiResponse_t> m_GetTicketForWebApiResponse;
void Start()
{
if (SteamManager.Initialized)
{
// 获取 steam 用户信息
CSteamID cSteamID = SteamUser.GetSteamID();
var mSteamID = cSteamID.m_SteamID;
// 发起获取票据请求https://partner.steamgames.com/doc/api/ISteamUser#GetAuthTicketForWebApi
SteamUser.GetAuthTicketForWebApi(mSteamID.ToString());
}
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
SteamAPICall_t handle = SteamUserStats.GetNumberOfCurrentPlayers();
m_NumberOfCurrentPlayers.Set(handle);
NtLog.Log(NtLog.NtLogLevel.Debug, Tag, "Called GetNumberOfCurrentPlayers()");
}
}
/**
* 我们通常在 OnEnable 中执行此操作,因为这允许我们在 Unity 重新加载程序集后重新创建回调。
*/
private void OnEnable()
{
m_GameOverlayActivated = Callback<GameOverlayActivated_t>.Create(OnGameOverlayActivated);
m_GetTicketForWebApiResponse = Callback<GetTicketForWebApiResponse_t>.Create(OnGetTicketForWebApiResponse);
}
private void OnDisable()
{
m_GameOverlayActivated = null;
m_GetTicketForWebApiResponse = null;
}
private void OnGameOverlayActivated(GameOverlayActivated_t pCallback)
{
if (pCallback.m_bActive != 0)
{
NtLog.Log(NtLog.NtLogLevel.Debug, Tag, "Steam Overlay has been activated");
}
else
{
NtLog.Log(NtLog.NtLogLevel.Debug, Tag, "Steam Overlay has been closed");
}
}
private void OnGetTicketForWebApiResponse(GetTicketForWebApiResponse_t pCallback)
{
NtLog.Log(NtLog.NtLogLevel.Information, tag, "Get ticket code:", pCallback.m_eResult);
if (pCallback.m_eResult == EResult.k_EResultOK)
{
// 获取成功
// 将 GetAuthTicketForWebApi 中的二进制票证数据转换为十六进制字符串
//
string ticket = BitConverter.ToString(pCallback.m_rgubTicket);
// 请求验证
var mSteamID = SteamUser.GetSteamID().m_SteamID;
if (mSteamID == 0 || string.IsNullOrEmpty(ticket))
{
NtLog.Log(NtLog.NtLogLevel.Error, Tag, "steam id or ticket is null.");
return;
}
// 将票据发送到你的服务器验证
GetThirdLoginUserInfo(mSteamID.ToString(), ticket);
}
else
{
// 其他失败的处理
}
}
/**
* 三方登录,后续有其他三方登录,可以移到其他地方封装,整理框架模式
*/
internal void GetThirdLoginUserInfo(string thirdUid, string thirdToken)
{
// 将 steam 票据信息发送到你的服务器验证
}
}
遇到的问题及注意点:
-
测试阶段,使用的不是商店的steam 账号,初始化也失败了。
-
appId 需要修改 两个地方,且必须修改,一个是项目自动生成的steam_appid.txt 文件,否则登录会失败,一个是 AppId_t 文件下的appId 。不能删除,否则还会自动生成错误的。除非修改自动生成的文件路径。
-
没有安装steam 时,无法初始化成功。下载 steam 和 登录账号后初始化成功。
-
没有登录steam 账号也会初始化失败。
-
以下情况都会初始化失败。参考官方文档:https://partner.steamgames.com/doc/api/steam_api#SteamAPI_RunCallbacks
-
Steam 客户端未运行。 需要有运行的 Steam 客户端才能提供各种 Steamworks 接口的实现。
-
Steam 客户端无法判定游戏的 App ID。 如果您直接通过可执行文件或调试器运行您的应用程序,那么您的游戏目录中的可执行文件旁,必须有一个
steam_appid.txt
,其中只记录了您的应用 ID,此外不含有任何其他内容。 Steam 将在当前工作目录中查找此文件。 如果您从不同的目录中运行可执行文件,您也许需要重新定位steam_appid.txt
文件。 -
您的应用程序运行的 OS 用户上下文,与 Steam 客户端并不相同,比如用户或管理员访问权限级别不同。
-
确定您在当前活跃的 Steam 帐户中拥有该 App ID 的许可。 您的游戏必须显示在您的 Steam 库中。
-
您的 AppID 未完全设置,如
发行状态:不可用
,或缺失默认程序包。
-
支付的实现
待实现