Steam游戏上架五:U3D连接Steamworks SDK制作成就系统

235 篇文章 23 订阅

Steam后台会解锁以达成的成就,并弹小窗给玩家,类似这样:

这里写图片描述

实现 Steam成就系统  步骤:

    1. 下载安排steamwork的SDK插件

    2. 从Steam后端设置用户成就(和统计)数据API

    3. 回调并迭代每项数据并初始化游戏状态

    4. 解锁成就

    5. 在游戏中显示成就

    6. 变更统计数值并上传

下面展开步骤:

一、安装steamwork.net SDK插件
在Github下载最新的版本:https://github.com/rlabrecque/Steamworks.NET
将所有内容导入Assets文件夹
启动Unity,编辑器会把steam_appid.txt这个文件拷贝到根目录
打开steam_appid.txt,把480改成你的AppID(480是Steam的示例工程ID,建议没做过的人先拿480来测试,成功了再移 植到自己的游戏项目里)

更改脚本 SteamManager.cs 找到  SteamAPI.RestartAppIfNecessary(AppId_t.Invalid)将AppId_t.Invalid替换成(AppId_t)480" 或者 "new AppId_t(480),480改成自己的APP ID如图:

重启unity,保证 steam_appid.txt 已生效.

如何使用

1.找到SteamManagers.cs

2.将SteamManager.cs脚本挂在GameObject上,steam会自动生成单例

3.完整C#接口请点击查看

注:需要在https://partner.steamgames.com/home下载sdk,里面有提交游戏的工具,在\sdk\tools\ContentBuilder\builder
        在https://partner.steamgames.com/home/steamworks可以查看文档
        在http://steamworks.github.io/gettingstarted/可以查看C#接口的使用方式

 


二、 从Steam后端设置用户成就(和统计)数据API

官方API文档说明:https://partner.steamgames.com/doc/api/ISteamUserStats#SetAchievement

解锁成就方法:

SetAchievement

bool SetAchievement( const char *pchName );

NameTypeDescription
pchNameconst char *The 'API Name' of the Achievement to unlock.


Unlocks an achievement.

You must have called RequestCurrentStats and it needs to return successfully via its callback prior to calling this!

You can unlock an achievement multiple times so you don't need to worry about only setting achievements that aren't already set. This call only modifies Steam's in-memory state so it is quite cheap. To send the unlock status to the server and to trigger the Steam overlay notification you must call StoreStats.
 //如果成就处在解锁状态,则调用StoreStats上传解锁状态到steam页面
Returns: bool
This function returns true upon success if all of the following conditions are met; otherwise, false.

  • The specified achievement "API Name" exists in App Admin on the Steamworks website, and the changes are published.
  • RequestCurrentStats has completed and successfully returned its callback.


See Also: RequestCurrentStatsStoreStatsResetAllStatsGetAchievementAndUnlockTimeGetAchievement

 

这个是官方的示例工程,其实我只是把官方的代码精练了一遍,剔除我不需要的部分,留下主干,这样便于快速理解。官方示例的下载地址是:https://github.com/rlabrecque/Steamworks.NET

下面就是官方案例,每一个按钮被点击时,当条件触发便达成成就。比如第一次点击“Set State to Winner”即解锁ACH_WIN_ONE_GAME,点击100次之后达成ACH_WIN_100_GAMES. 我把这些功能剔除掉,先以“一进入游戏便达成一个成就”为目的。好吧,我们一步步来实现。

这里要提示一句,拿示例工程做测试的朋友,不要改脚本里成就的ID! 它必须与Steam后台里被录入的API Name保持一致,不然你测试的时候成就是读取不到的。

 

三、 回调并迭代每项数据并初始化游戏状态

   构造函数初始化游戏状态

 

 四、解锁成就

五、上传解锁状态到steam页面

 六、变更统计数值并上传

 

小结:

 

​​​--SDK调用为异步调用,用来向 Steam 请求当前用户的统计与成就。 您必须先进行此调用,才能设置统计或成就。 在构造函数内对此方法进行首次调用。 日后若需检查更新后的统计与成就,可随时调用此方法。
    CS.Steamworks.SteamUserStats.RequestCurrentStats();  --请求成就状态


    CS.Steamworks.SteamUserStats.SetStat("stat_4", 1);  --设置统计进度(进度条)


    CS.Steamworks.SteamUserStats.SetAchievement();  --解锁成就


    --但凡您需要更新用户的统计信息时,应进行此调用。
    CS.Steamworks.SteamUserStats.StoreStats();  --提交成就,实时刷新,不然的话会在游戏结束才会提示成就解锁

 

下面是完整代码,我剔除了很多东西,别的功能你们可以自己加。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.ComponentModel;
using Steamworks;

class AchievementManager : MonoBehaviour
{
//成就
private enum Achievement : int
{
ACH_WIN_ONE_GAME,
//有待添加
};

 

private Achievment_t[] m_Achievements = new Achievment_t[]
{
    new Achievment_t(Achievement.ACH_WIN_ONE_GAME, "第一个成就","启动游戏立即获得"),
};

private class Achievment_t
{
    public Achievement m_eAchievementID;
    public string m_strName;
    public string m_strDescription;
    public bool m_bAchieved;

    public Achievment_t(Achievement achivementID, string name, string desc)
    {
        m_eAchievementID = achivementID;
        m_strName = name;
        m_strDescription = desc;
        m_bAchieved = false;
    }
}

//游戏状态
private enum GameState
{
    GAME_ACTIVE,
    //有待添加
};

//GameID
private CGameID m_GameID;

//从Steam获取统计数据?
private bool m_bRequestedStats;
private bool m_bStatsValid;

//这一帧存储统计数据?
private bool m_bStoresStats;

//游戏数据
private int m_nTotalNumWins;

protected Callback<UserStatsReceived_t> m_UserStatsReceived;
protected Callback<UserStatsStored_t> m_UserStatsStored;
protected Callback<UserAchievementStored_t> m_UserAchievementStored;

//把回调创建放在OnEnable方法内以确保Unity加载完成后重复创建回调
private void OnEnable()
{
    if (!SteamManager.Initialized) return;

    m_GameID = new CGameID(SteamUtils.GetAppID());

    m_UserStatsReceived = Callback<UserStatsReceived_t>.Create(OnUserStatsReceived);
    m_UserStatsStored = Callback<UserStatsStored_t>.Create(OnUserStatsStored);
    m_UserAchievementStored = Callback<UserAchievementStored_t>.Create(OnAchievementStored);

    m_bRequestedStats = false;
    m_bStatsValid = false;
}

private void Start()
{
    m_nTotalNumWins = 0;
    OnGameStateChange(GameState.GAME_ACTIVE);
}

private void Update()
{
    if (!SteamManager.Initialized) return;

    if (!m_bRequestedStats)
    {
        if (!SteamManager.Initialized)
        {
            m_bRequestedStats = true;
            return;
        }
        //从 Steam 后端调出用户的统计与成就数据
        bool bSuccess = SteamUserStats.RequestCurrentStats();
        m_bRequestedStats = bSuccess;
    }
    //if (!m_bStatsValid) return;

    foreach (Achievment_t achievement in m_Achievements)
    {
        if (achievement.m_bAchieved) continue;
        switch (achievement.m_eAchievementID)
        {
            case Achievement.ACH_WIN_ONE_GAME:
                if (m_nTotalNumWins !=0)
                {UnlockAchievement(achievement);}
                break;
        }
    }
    //在游戏中的某个节点上传变更
    if (m_bStoresStats)
    {
        SteamUserStats.SetStat("NumWins", m_nTotalNumWins);
        bool bSuccess = SteamUserStats.StoreStats();
        m_bStoresStats = !bSuccess;
    }

}

// 数据准备完成后(RequestCurrentStats),回调
private void OnUserStatsReceived(UserStatsReceived_t pCallback)
{
    if (!SteamManager.Initialized) return;
    if ((ulong)m_GameID == pCallback.m_nGameID)
    {
        //加载成就
        if (EResult.k_EResultOK == pCallback.m_eResult)
        {
            Debug.Log("Received stats and achievements from Steam");
            m_bStatsValid = true;

            foreach (Achievment_t ach in m_Achievements)
            {
                //迭代每项数据并初始化游戏状态
                bool ret = SteamUserStats.GetAchievement(ach.m_eAchievementID.ToString(), out ach.m_bAchieved);

                if (ret)
                {
                    //在游戏里显示成就的可读属性(name&des)
                    ach.m_strName = SteamUserStats.GetAchievementDisplayAttribute(ach.m_eAchievementID.ToString(), "name");
                    ach.m_strDescription = SteamUserStats.GetAchievementDisplayAttribute(ach.m_eAchievementID.ToString(), "desc");
                }
                else
                {
                    Debug.LogWarning("failed for getting achievement" + ach.m_eAchievementID);
                }
            }

            SteamUserStats.GetStat("NumWins", out m_nTotalNumWins);
        }
        else
            Debug.Log("RequestStats - failed, " + pCallback.m_eResult);
    }
}


//回调上传的变更(StoreStats)
private void OnUserStatsStored(UserStatsStored_t pCallback)
{
    if ((ulong)m_GameID == pCallback.m_nGameID)
    {
        if (EResult.k_EResultOK == pCallback.m_eResult)
        {
            Debug.Log("StroeStats-success");
        }
        else if (EResult.k_EResultInvalidParam == pCallback.m_eResult)
        {
            Debug.Log("StoreStats-failed to validate");
            UserStatsReceived_t callback = new UserStatsReceived_t();
            callback.m_eResult = EResult.k_EResultOK;
            callback.m_nGameID = (ulong)m_GameID;
            OnUserStatsReceived(callback);
        }
        else
        {
            Debug.Log("failed-StroeStats");
        }
    }
}


//解锁成就
private void UnlockAchievement(Achievment_t achievement)
{
    achievement.m_bAchieved = true;
    SteamUserStats.SetAchievement(achievement.m_eAchievementID.ToString());
    m_bStoresStats = true;
}


//回调解锁的成就
private void OnAchievementStored(UserAchievementStored_t pCallback)
{
    if ((ulong)m_GameID == pCallback.m_nGameID)
    {
        if (0 == pCallback.m_nMaxProgress)
        {
            Debug.Log("Achievement" +pCallback.m_rgchAchievementName+"unlocked");
        }
        else
        {
            Debug.Log("Achievement '" + pCallback.m_rgchAchievementName + "' progress callback, (" + pCallback.m_nCurProgress + "," + pCallback.m_nMaxProgress + ")");
        }
    }
}


//切换游戏状态
private void OnGameStateChange(GameState eNewState)
{
    //if (!m_bStatsValid) return;
    if (eNewState == GameState.GAME_ACTIVE)
    {
        m_nTotalNumWins++;
    }
    m_bStoresStats = true;
}
 

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值