跳到主要内容
版本:v4

快速接入

功能概述

  • 成就系统让玩家在游戏中完成特定目标时获得成就,提升游戏参与度和玩家粘性。支持普通成就、分步成就、隐藏成就与白金成就。
  • 更详细的功能介绍请参考成就系统功能介绍

集成步骤

  • 本文档以 C++ 为例演示成就系统集成步骤,其他语言可参考相应的 DLL 调用方式。
  • 在集成成就系统之前,请先阅读快速开始了解基本的集成流程,并完成 SDK 初始化与启动校验。
初始化要求

调用成就系统任何 API 函数前,必须先成功调用 TapSDK_Init 进行初始化。未初始化或初始化失败时,调用成就函数将返回错误或者非预期结果。

1. 解锁成就

当玩家达成某一成就时,调用 TapAchievement_AsyncUnlock() 解锁成就。结果通过 TapEventID::AchievementUnlock 回调返回:

#include <atomic>
#include <iostream>
#include <thread>

#include "taptap_achievement.h"

using namespace std;

atomic<int64_t> gRequestID;

// 解锁成就回调函数
void unlockCallback(TapEventID eventID, void* data)
{
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapAchievementUnlockResponse*>(data);
if (resp->error == nullptr) { // 解锁请求成功
if (resp->achievement != nullptr) { // 检查 achievement 是否为空
const auto& achievement = *resp->achievement;
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << "unlock callback success: id=" << achievement.id
<< ", name=" << achievement.name
<< ", current_steps=" << achievement.current_steps
<< ", newly_unlocked=" << achievement.newly_unlocked << endl;
}
// 只有当 platinum_achievement 不为 nullptr 时才尝试解引用
if (resp->platinum_achievement != nullptr) {
const auto& platinum = *resp->platinum_achievement;
cout << "platinum unlocked: id=" << platinum.id
<< ", newly_unlocked=" << platinum.newly_unlocked << endl;
}
} else { // 解锁请求失败,处理错误
cout << "unlock callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}

int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成

// 1. 注册解锁成就回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::AchievementUnlock, unlockCallback);

// 2. 构建解锁成就的请求
TapAchievementUnlockRequest req;
// 结构体"零值化",避免内存随机值导致的野指针问题
// C++11 及以上,可以使用 TapAchievementUnlockRequest req{};,无需 memset
memset(&req, 0, sizeof(req));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
req.achievement_id = "your_achievement_id"; // 开发者中心配置的成就 ID

// 3. 发起解锁成就的异步请求
auto ret = TapAchievement_AsyncUnlock(
TapAchievement(), // 成就模块单例对象
++gRequestID, // 请求 ID,由开发者生成,用于在回调函数中对应到原始请求
&req);
if (ret != TapSDK_Result_OK) { // 请求发起失败,不会触发回调,请根据返回值做相应处理
cout << "TapAchievement_AsyncUnlock failed, ret=" << ret << endl;
return -1;
}

// 请求发起成功,等待回调函数返回处理结果

// 4. 游戏主循环
bool running = true;
while (running) {
// 处理 SDK 回调事件
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...

// 控制帧率,请按游戏实际需求调整
this_thread::sleep_for(chrono::milliseconds(100));
}

// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
信息

对已解锁的成就重复调用,服务端不会重复记录,回调中 achievement->newly_unlockedfalse

2. 分步成就增长步数

对于需要多步完成的分步成就,调用 TapAchievement_AsyncIncrement() 累加步数。SDK 自动累计步数,步数达到成就解锁阈值时成就自动解锁,回调中 achievement->newly_unlockedtrue

#include <atomic>
#include <iostream>
#include <thread>

#include "taptap_achievement.h"

using namespace std;

atomic<int64_t> gRequestID;

// 分步成就增长回调函数
void incrementCallback(TapEventID eventID, void* data)
{
// 注意:data 及其里面引用的其他内存,在回调函数返回后会被 SDK 释放。如需长期使用,请开发者自行复制一份
auto resp = static_cast<TapAchievementIncrementResponse*>(data);
if (resp->error == nullptr) { // 步数增加成功
if (resp->achievement != nullptr) { // 检查 achievement 是否为空
const auto& achievement = *resp->achievement;
// 注意:所有字符串字段(char*)均为 UTF-8 编码,请根据需要自行转换
cout << "increment callback success: id=" << achievement.id
<< ", name=" << achievement.name
<< ", current_steps=" << achievement.current_steps
<< ", newly_unlocked=" << achievement.newly_unlocked << endl;
}
// 只有当 platinum_achievement 不为 nullptr 时才尝试解引用
if (resp->platinum_achievement != nullptr) {
const auto& platinum = *resp->platinum_achievement;
cout << "platinum unlocked: id=" << platinum.id
<< ", newly_unlocked=" << platinum.newly_unlocked << endl;
}
} else { // 步数增加失败,处理错误
cout << "increment callback failed, code=" << resp->error->code
<< ", message=" << resp->error->message << endl;
}
}

int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成

// 1. 注册分步成就增长回调函数,只需注册一次
TapSDK_RegisterCallback(TapEventID::AchievementIncrement, incrementCallback);

// 2. 构建分步成就增长的请求
TapAchievementIncrementRequest req;
// 结构体"零值化",避免内存随机值导致的野指针问题
// C++11 及以上,可以使用 TapAchievementIncrementRequest req{};,无需 memset
memset(&req, 0, sizeof(req));
// 注意:所有字符串字段(char*)必须使用 UTF-8 编码
req.achievement_id = "your_achievement_id"; // 开发者中心配置的成就 ID
req.steps = 1; // 本次增加的步数

// 3. 发起分步成就增长的异步请求
auto ret = TapAchievement_AsyncIncrement(
TapAchievement(), // 成就模块单例对象
++gRequestID, // 请求 ID,由开发者生成,用于在回调函数中对应到原始请求
&req);
if (ret != TapSDK_Result_OK) { // 请求发起失败,不会触发回调,请根据返回值做相应处理
cout << "TapAchievement_AsyncIncrement failed, ret=" << ret << endl;
return -1;
}

// 请求发起成功,等待回调函数返回处理结果

// 4. 游戏主循环
bool running = true;
while (running) {
// 处理 SDK 回调事件
TapSDK_RunCallbacks();
// 您的游戏逻辑
// ...

// 控制帧率,请按游戏实际需求调整
this_thread::sleep_for(chrono::milliseconds(100));
}

// 5. 清理资源
TapSDK_Shutdown();
return 0;
}
信息

分步成就的步数只能增加,不能减少或重置。非分步成就不能调用此接口,否则回调会返回错误。

3. 打开成就展示页

调用 TapAchievement_ShowAchievements() 打开成就展示页,展示玩家所有成就及达成情况。该接口为同步调用,无需等待回调:

#include <iostream>

#include "taptap_achievement.h"

using namespace std;

int main()
{
// 这里省略 SDK 初始化和启动校验相关代码,假设已经正确完成

auto ret = TapAchievement_ShowAchievements(TapAchievement());
if (ret != TapSDK_Result_OK) { // 打开失败,请根据返回值做相应处理
cout << "TapAchievement_ShowAchievements failed, ret=" << ret << endl;
return -1;
}

TapSDK_Shutdown();
return 0;
}

错误码

  • 接口调用返回值均为 TapSDK_Result,可根据该值做提示或重试。详见TapSDK_Result
    • 返回值非 TapSDK_Result_OK 时,表示请求发起失败,后续不会触发回调。
  • 回调函数中 resp->error 非空时,表示请求失败,可根据 TapSDK_ErrorCode 做提示或重试。详见TapSDK_ErrorCode