# 演练模式

> 来源：https://help.gravity-engine.com/docs/client-sdk/unity/advanced/dry-run-mode
> 说明 Unity SDK 如何通过 DryRunEventWithCallback 接入引力演练模式，包含 trace_id 获取、回调处理与付费/关键行为向媒体回传的示例代码。



> **注意**
> 此文档主要说明引力 Unity SDK 演练模式相关的代码接入部分。运营和投放的后台配置请参考[引力 & 回传演练模式](https://gravityengine.feishu.cn/wiki/G6lwwJn8NiDr9wkYUZFcp5wonme?fromScene=spaceOverview)。
>
> Unity 支持演练模式，可开启演练的媒体按**应用类型**区分，与各类型对应平台的支持范围一致：
>
> * Android 应用：巨量 & 腾讯 & 百度 & 快手 & TapTap
> * iOS 应用：仅腾讯
> * 鸿蒙应用：仅巨量

为了该模式更灵活的使用，建议将演练模式在代码中配置为一个开关，方便联调和测试。

## 接入事项 [#接入事项]

因演练模式主要是为了付费的自定义回传，为了减少投放每次调整映射策略，导致的客户端频繁改动，引力提供了演练模式，支持客户端技术从引力获取具体订单对应的回传结果，再执行给媒体的回传。

请客户端技术务必确认下面的流程图步骤明确后开始接入。

### Unity SDK 演练 [#unity-sdk-演练]

以下是 Unity SDK，技术需要处理的 5 大步骤：

1. 升级引力 SDK 到 [5.0.29](https://github.com/GravityInfinite/GravityEngine-Unity-Demo/releases) 及以上版本，建议使用最新版本；
2. 正常按照[引力接入文档](/docs/client-sdk/unity/quickstart)接入；
3. 在用户发生付费行为时，客户端需要获取到 `trace_id`，获取方式：
   1. **如果历史是通过客户端上报付费事件给引力**：调用引力 SDK 付费事件上报接口 `trackPayEvent`，该接口会返回一个 `trace_id`，请使用变量保存好；
   2. **如果历史是通过服务端 API 上报付费事件给引力**：API 上报之后，您的服务端需要返回本次事件上报的 `$order_id` 给您的客户端，此时 `$order_id` 即为 `trace_id`
4. 然后调用 `DryRunEventWithCallback` 接口，传入上一步获取的 `trace_id`；
5. 在 `DryRunEventWithCallback` 方法的回调函数中根据返回的信息来执行向媒体 SDK 上报事件的逻辑；

核心代码实现逻辑如下，请注意看注释！

```csharp
public class QueryDryRunCallbackImpl : IQueryDryRunCallback
{
    public void onFailed(string errorMsg)
    {
        Debug.Log("query failed  with message " + errorMsg);
    }

    void onEmpty(GravityEngineAPI.DryRunEventEmpty type)
    {
        // type枚举：NOT_ENABLE 当前用户归因媒体未开启演练模式；NO_IN_POSTBACK_WINDOW 未在窗口期；SKIP 扣量不回传
        // 当前未查询到需要给媒体上报的付费事件
    }

    public void onTrackPay(int backValue, string company, Dictionary<string, object> otherParams)
    {
        // 可以从 otherParams 中解析自己传入的参数使用
        if (company.Equals("bytedance"))
        {
            // 2. 调用巨量的上报付费的方法，传入金额 backValue
            // 客户实现
        }
        else if (company.Equals("tencent"))
        {
            // 2. 调用腾讯的上报付费的方法，传入金额 backValue
            // 客户实现
        }
    }

    public void onTrackKeyActive(string company, Dictionary<string, object> otherParams)
    {
        // 可以从 otherParams 中解析自己传入的参数使用
        if (company.Equals("bytedance"))
        {
            // 2. 调用巨量的上报关键行为的方法
            // 客户实现
        }
        else if (company.Equals("tencent"))
        {
            // 2. 调用腾讯的上报关键行为的方法
            // 客户实现
        }
    }
}

// 演练模式-付费案例
string traceId = GravityEngineAPI.TrackPayEvent(300, "CNY", "your_order_id", "月卡", "支付宝");
Dictionary<string, object> payOtherParams = new Dictionary<string, object>();
payOtherParams["name"] = "flower";
payOtherParams["id"] = "008";
payOtherParams["num"] = 1;
payOtherParams["channel"] = "wechat";
payOtherParams["currency"] = "￥";
GravityEngineAPI.DryRunEventWithCallback(traceId, payOtherParams, new QueryDryRunCallbackImpl());

// 演练模式-关键行为案例
string keyActiveTraceId = GravityEngineAPI.Track("在引力定义的关键行为事件");
Dictionary<string, object> keyActiveOtherParams = new Dictionary<string, object>();
keyActiveOtherParams["origin_event"] = "游戏过关事件";
GravityEngineAPI.DryRunEventWithCallback(keyActiveTraceId, keyActiveOtherParams, new QueryDryRunCallbackImpl());
```

上述示例中 `GravityEngineAPI` 为引力 Unity SDK 的实例，请先完成 SDK 初始化（setupAndStart）后再调用演练模式相关接口。

`onTrackPay` 回调中的 `payAmount` 参数单位是分，给具体媒体回传的时候，请留意是否需要转化成元\~

## 常见问题 [#常见问题]

1. **如果代码执行了演练模式的部分，但是应用没有配置，演练模式是否生效？**

   1. 不开启演练模式，调用演练模式的接口会返回 `onEmpty`（当前用户归因媒体未开启演练模式）；
   2. 需同时开启，否则演练模式不生效。

2. **是否有相关接口能获取到应用管理的演练模式是否开启以及选择的类型？**

   1. 暂时无法获取。

3. **如何验证演练模式接入是否成功？**

   1. 在引力后台开启演练模式，调用演练模式之后验证返回的数据是否符合配置的映射。

4. **当前用户归因媒体未开启演练模式怎么理解？**

   1. 当用户来自**暂不支持演练的渠道或未开启演练模式**时会显示此提示。Unity 端可开启演练的媒体按**应用类型**区分，Android、iOS、鸿蒙应用分别与其对应平台的支持范围一致；其他渠道及自然量用户均会返回此状态。

5. **订单细查 SDK 回传状态分别是什么含义？**

   1. 等待判断：条件映射状态为未通过的；
   2. 无需 SDK 回传：满足 SDK 映射的条件及回传比例，执行扣传；
   3. SDK 待回传：等待 SDK 返回回传结果，一般是没有调用演练模式接口；
   4. SDK 已回传：已通过 SDK 回传。
