NLDClient-yudde/ProjectNLD/Assets/Code/Scripts/Framework/BI/BIManager.cs

567 lines
16 KiB
C#
Raw Normal View History

2025-03-18 18:40:56 +08:00
using Cysharp.Threading.Tasks;
2025-03-18 19:13:40 +08:00
using Newtonsoft.Json;
2024-05-14 15:29:31 +08:00
using PhxhSDK;
2024-07-25 17:06:02 +08:00
using System;
2024-05-14 15:29:31 +08:00
using System.Collections.Generic;
using UnityEngine;
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
public partial class BIManager : Singlenton<BIManager>, IInitable, IUpdatable
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
// 关卡属性
private BILevelInfo LevelInfo;
2024-05-14 15:29:31 +08:00
private IBIService _biService;
private StorageEvent _storageEvent;
2025-04-22 15:39:26 +08:00
private bool _isInit;
private bool sendPhxh = false;
2024-05-31 14:26:33 +08:00
private Dictionary<string, object> _tempEventDictionary = new(4);
2024-09-18 14:51:32 +08:00
2025-04-22 15:39:26 +08:00
#region 网络状态和发送周期相关
/// <summary>
/// 事件队列
/// </summary>
2024-09-18 14:51:32 +08:00
private Queue<(string, Dictionary<string, object>)> eventQueue = new();
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
/// <summary>
/// 是否使用队列模式(无网络或设置了发送周期)
/// </summary>
private bool _useQueueMode = false;
/// <summary>
/// 发送周期 默认1秒
/// </summary>
private float _sendInterval = 1.0f;
/// <summary>
/// 网络状态 通过心跳包检测
/// </summary>
private bool _networkAvailable = true;
/// <summary>
/// 计时器
/// </summary>
private float _timer = 0f;
#endregion
#region 基本属性
/// <summary>
/// 设备机型
/// </summary>
2025-03-19 14:05:27 +08:00
private string deviceInfo;
2025-04-22 15:39:26 +08:00
/// <summary>
/// 设备ID
/// </summary>
2025-03-19 14:05:27 +08:00
private string deviceID;
2025-04-22 15:39:26 +08:00
/// <summary>
/// 版本
/// </summary>
2025-03-19 14:05:27 +08:00
private string gameVersion;
2025-04-22 15:39:26 +08:00
/// <summary>
/// 平台
/// </summary>
2025-03-19 14:05:27 +08:00
private string platform;
2025-04-22 15:39:26 +08:00
/// <summary>
/// 渠道
/// </summary>
2025-03-19 14:05:27 +08:00
private string channel;
2025-04-22 15:39:26 +08:00
/// <summary>
/// 剩余存储空间
/// </summary>
2025-03-19 14:05:27 +08:00
private int storageInfo;
2025-04-22 15:39:26 +08:00
#endregion
#region 初始化
2024-05-14 15:29:31 +08:00
public void Init()
{
InitBiService();
2025-03-20 14:20:08 +08:00
#if BI_PHXH
2025-04-22 15:39:26 +08:00
sendPhxh = true;
2025-03-20 14:20:08 +08:00
#endif
2024-05-14 15:29:31 +08:00
LevelInfo = new BILevelInfo();
_storageEvent = StorageMgr.Instance.GetStorage<StorageEvent>("StorageEvent");
_storageEvent ??= new StorageEvent();
_isInit = true;
2025-04-22 15:39:26 +08:00
// 初始化网络状态
RegisterHeartbeatEvents();
//初次启动游戏打点
2025-02-18 13:23:46 +08:00
//TrackEventOnce(BI_GameStart, param: new Dictionary<string, object>() { { "event", "first_open" } });
2024-05-14 15:29:31 +08:00
}
2025-04-22 15:39:26 +08:00
/// <summary>
/// 登陆后初始化信息
/// </summary>
/// <param name="name"></param>
public void BiAfterLoginInit(SDKManager.SdkName name)
{
_biService = SDKManager.Instance.GetSdkHelper(name) as IBIService;
if (_biService == null)
{
DebugUtil.Log("Get BI Service error, SDK helper name is {0}", name);
return;
}
// 设置登陆后才有的基本属性 如用户ID
_biService.SetUser(SDKManager.Instance.ApplicationUserID);
SendQueuedEvents();
}
2024-05-14 15:29:31 +08:00
private void InitBiService()
{
2024-05-31 14:26:33 +08:00
var helperName = SDKManager.SdkName.TapTap;
2025-04-22 15:39:26 +08:00
2024-05-31 14:26:33 +08:00
#if SDK_FIREBASE
helperName = SDKManager.SdkName.FireBase;
2024-05-14 15:29:31 +08:00
_biService = SDKManager.Instance.GetSdkHelper(helperName) as IBIService;
2024-05-31 14:26:33 +08:00
#endif
2024-07-22 17:08:02 +08:00
2024-05-31 14:26:33 +08:00
#if SDK_TAPTAP
helperName = SDKManager.SdkName.TapTap;
2025-04-22 15:39:26 +08:00
_biService = SDKManager.Instance.GetSdkHelper(helperName) as IBIService;
2024-05-31 14:26:33 +08:00
#endif
2024-07-22 17:08:02 +08:00
#if SDK_TALKINGDATA
2024-09-18 14:51:32 +08:00
helperName = SDKManager.SdkName.TalkingData;
_biService = SDKManager.Instance.GetSdkHelper(helperName) as IBIService;
2024-07-22 17:08:02 +08:00
//TD在登录后初始化
2025-04-22 15:39:26 +08:00
#endif
2024-05-14 15:29:31 +08:00
if (_biService == null)
{
2024-05-31 16:36:36 +08:00
DebugUtil.Log("Get BI Service error, SDK helper name is {0}", helperName);
2024-05-14 15:29:31 +08:00
return;
2024-05-31 14:26:33 +08:00
}
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
// 初始化基本属性
2025-03-19 14:05:27 +08:00
deviceInfo = SystemInfo.deviceModel;
storageInfo = SystemInfo.systemMemorySize;
deviceID = SystemInfo.deviceUniqueIdentifier;
gameVersion = Application.version;
platform = DeviceHelper.GetPlatformString();
channel = PlayerPrefs.GetString("BI_Platform", "test");
2025-04-22 15:39:26 +08:00
// TODO 设置通用属性 例如 服务器
_biService?.SetUserProperty("platform", DeviceHelper.GetPlatformString());
2025-03-19 14:05:27 +08:00
DebugUtil.Log("device platform:{0}", platform);
2025-04-22 15:39:26 +08:00
2025-03-19 14:05:27 +08:00
#if SDK_TALKINGDATA
_biService?.SetUserProperty(TalkingDataProfileParamName.Param1, deviceInfo);
_biService?.SetUserProperty(TalkingDataProfileParamName.Param2, storageInfo.ToString() + "MB");
#endif
2024-05-14 15:29:31 +08:00
}
2024-07-22 17:08:02 +08:00
2025-04-22 15:39:26 +08:00
/// <summary>
/// 注册心跳包相关事件,用于检测网络状态
/// </summary>
private void RegisterHeartbeatEvents()
2024-07-22 17:08:02 +08:00
{
2025-04-22 15:39:26 +08:00
// 注册心跳包响应事件
Framework.EventManager.Instance.Register(Framework.EventManager.EventName.NetHandshakeDone,
(Action<uint>)OnNetworkConnected);
Framework.EventManager.Instance.Register(Framework.EventManager.EventName.NetError,
(Action<uint>)OnNetworkError);
// 初始状态假设网络可用,但使用队列模式
_networkAvailable = true;
_useQueueMode = _sendInterval > 0;
2024-07-22 17:08:02 +08:00
}
2024-05-14 15:29:31 +08:00
2025-02-11 14:40:04 +08:00
/// <summary>
/// 设置用户属性
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
public void SetUserProperty(string key, string value)
{
if (!_isInit)
return;
_biService?.SetUserProperty(key, value);
}
2025-04-22 15:39:26 +08:00
#endregion
#region 释放
public void Release()
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
_tempEventDictionary = null;
// 在释放时尝试发送剩余的队列事件
if (_isInit && _networkAvailable && eventQueue.Count > 0 && _biService != null)
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
SendQueuedEvents();
}
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
// 注销事件监听
Framework.EventManager.Instance.Unregister(Framework.EventManager.EventName.NetHandshakeDone,
(Action<uint>)OnNetworkConnected);
Framework.EventManager.Instance.Unregister(Framework.EventManager.EventName.NetError,
(Action<uint>)OnNetworkError);
}
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
#endregion
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
#region 周期发送
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
public void Update(float deltaTime)
{
if (!_isInit)
return;
// 如果队列中有事件并且有网络连接
if (eventQueue.Count > 0 && _networkAvailable)
{
// 如果使用周期发送模式
if (_sendInterval > 0)
{
_timer += Time.deltaTime;
// 达到发送周期
if (_timer >= _sendInterval)
{
_timer = 0;
SendQueuedEvents();
}
}
// 如果不使用周期模式(立即发送)但是之前网络不可用导致有队列
2024-09-18 14:51:32 +08:00
else
{
2025-04-22 15:39:26 +08:00
SendQueuedEvents();
2024-09-18 14:51:32 +08:00
}
2024-05-14 15:29:31 +08:00
}
2025-04-22 15:39:26 +08:00
}
/// <summary>
/// 网络连接成功
/// </summary>
private void OnNetworkConnected(uint netID)
{
_networkAvailable = true;
_useQueueMode = _sendInterval > 0; // 如果有设置发送周期,仍然使用队列模式
// 如果不使用队列模式,立即发送所有队列中的事件
if (!_useQueueMode && eventQueue.Count > 0)
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
SendQueuedEvents();
2024-05-14 15:29:31 +08:00
}
}
2025-04-22 15:39:26 +08:00
/// <summary>
/// 网络连接错误
/// </summary>
private void OnNetworkError(uint netID)
{
2025-04-22 15:39:26 +08:00
_networkAvailable = false;
_useQueueMode = true; // 网络错误时启用队列模式
}
2025-04-22 15:39:26 +08:00
/// <summary>
/// 设置事件发送周期
/// </summary>
/// <param name="interval">发送周期,单位秒,设为0则立即发送</param>
public void SetSendInterval(float interval)
{
_sendInterval = Mathf.Max(0, interval);
_useQueueMode = !_networkAvailable || _sendInterval > 0;
}
2025-04-22 15:39:26 +08:00
#endregion
2025-04-22 15:39:26 +08:00
#region 发送事件
2025-04-22 15:39:26 +08:00
/// <summary>
/// 发送队列中的所有事件
/// </summary>
private void SendQueuedEvents()
{
if (_biService == null || !_networkAvailable)
return;
2025-04-22 15:39:26 +08:00
while (eventQueue.Count > 0)
{
2025-04-22 15:39:26 +08:00
//将缓存的事件上报
var (eventName, param) = eventQueue.Dequeue();
_biService.ReportEvent(eventName, param);
TrackEventPhxh(eventName, param);
}
}
2024-05-14 15:29:31 +08:00
/// <summary>
2025-04-22 15:39:26 +08:00
/// 用于传输参数自定义命名事件 (普通事件)
/// </summary>
/// <param name="eventName"></param>
/// <param name="param"></param>
public void TrackEvent(string eventName, Dictionary<string, object> param)
{
if (!_isInit)
return;
try
{
2025-04-22 15:39:26 +08:00
// 使用队列模式或者服务未初始化时,暂存事件
if (_useQueueMode || _biService == null)
2024-09-18 14:51:32 +08:00
{
2025-04-22 15:39:26 +08:00
eventQueue.Enqueue((eventName, param));
2024-09-18 14:51:32 +08:00
}
else
{
2025-04-22 15:39:26 +08:00
_biService.ReportEvent(eventName, param);
TrackEventPhxh(eventName, param);
2024-09-18 14:51:32 +08:00
}
}
catch (Exception e)
{
2024-09-29 15:10:14 +08:00
DebugUtil.LogError("Track event fail! EventName:" + eventName + ",\n error msg: " + e.Message);
}
}
2024-05-14 15:29:31 +08:00
/// <summary>
2025-04-22 16:09:40 +08:00
/// 上报普通事件 TD有在用 谨慎删除
2024-05-14 15:29:31 +08:00
/// </summary>
2025-04-22 15:39:26 +08:00
public void TrackEvent(string eventName, string param1 = null, string param2 = null, string param3 = null)
2024-05-14 15:29:31 +08:00
{
if (!_isInit)
return;
try
{
_tempEventDictionary.Clear();
var userParam = _tempEventDictionary;
2025-04-22 15:39:26 +08:00
2024-05-14 15:29:31 +08:00
if (!string.IsNullOrEmpty(param1))
{
userParam.Add("param1", param1);
}
if (!string.IsNullOrEmpty(param2))
{
userParam.Add("param2", param2);
}
if (!string.IsNullOrEmpty(param3))
{
userParam.Add("param3", param3);
}
2024-09-18 14:51:32 +08:00
if (_biService != null)
{
2025-04-22 15:39:26 +08:00
_biService.ReportEvent(eventName, userParam);
2024-09-18 14:51:32 +08:00
}
else
{
2025-04-22 15:39:26 +08:00
eventQueue.Enqueue((eventName, userParam));
}
_tempEventDictionary.Clear();
}
catch (Exception e)
{
2025-04-22 15:39:26 +08:00
DebugUtil.LogError("BI Event: {0}, TrackEvent Error: {1}", eventName, e);
}
}
2025-04-22 15:39:26 +08:00
/// <summary>
2025-04-22 15:39:26 +08:00
/// 用于传输参数自定义命名事件 (一次性事件)
/// </summary>
/// <param name="firstEventName"></param>
/// <param name="param"></param>
2025-04-22 15:39:26 +08:00
public void TrackEventOnce(string firstEventName, Dictionary<string, object> param)
{
if (!_isInit)
return;
try
{
if (IsRecorded(firstEventName))
{
DebugUtil.Log("已经上报过 {0} 事件, 不会再次上报", firstEventName);
return;
}
2024-10-18 13:47:19 +08:00
_storageEvent.EventList.Add(firstEventName);
2025-04-22 15:39:26 +08:00
// 使用队列模式或者服务未初始化时,暂存事件
if (_useQueueMode || _biService == null)
2024-09-18 14:51:32 +08:00
{
2025-04-22 15:39:26 +08:00
eventQueue.Enqueue((firstEventName, param));
2024-09-18 14:51:32 +08:00
}
else
{
2025-04-22 15:39:26 +08:00
_biService.ReportEvent(firstEventName, param);
2024-09-18 14:51:32 +08:00
}
2025-04-22 15:39:26 +08:00
StorageMgr.Instance.SyncForce = true;
}
catch (Exception e)
{
DebugUtil.LogError("BI Event: {0}, TrackEventOnce Error: {1}", firstEventName, e);
}
}
2024-05-14 15:29:31 +08:00
/// <summary>
/// 上报关卡内普通事件
/// </summary>
2025-04-22 15:39:26 +08:00
public void TrackEventLevel(string eventName, BILevelInfo levelInfo, Dictionary<string, object> normalParam)
2024-05-14 15:29:31 +08:00
{
if (!_isInit)
return;
try
{
2025-04-22 15:39:26 +08:00
LevelInfo.Clone(levelInfo);
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
var levelParam = Utils.PropertiesNameValue2ObjectDictionary(LevelInfo);
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
foreach (var param in normalParam)
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
levelParam.Add(param.Key, param.Value);
2024-05-14 15:29:31 +08:00
}
2025-04-22 15:39:26 +08:00
// 使用队列模式或者服务未初始化时,暂存事件
if (_useQueueMode || _biService == null)
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
eventQueue.Enqueue((eventName, levelParam));
2024-05-14 15:29:31 +08:00
}
2025-04-22 15:39:26 +08:00
else
{
2025-04-22 15:39:26 +08:00
_biService.ReportEvent(eventName, levelParam);
TrackEventPhxh(eventName, levelParam);
}
}
catch (Exception e)
{
DebugUtil.LogError("BI Event: {0}, TrackEventLevel Error: {1}", eventName, e);
}
}
2024-05-14 15:29:31 +08:00
/// <summary>
/// 上报关卡内一次性事件
/// </summary>
2025-04-22 15:39:26 +08:00
public void TrackEventLevelOnce(string firstEventName, BILevelInfo levelInfo,
Dictionary<string, object> normalParam)
2024-05-14 15:29:31 +08:00
{
if (!_isInit)
return;
try
{
if (IsRecorded(firstEventName))
{
DebugUtil.Log("已经上报过 {0} 关卡事件,不会再次上报", firstEventName);
return;
}
2025-04-22 15:39:26 +08:00
LevelInfo.Clone(levelInfo);
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
var levelParam = Utils.PropertiesNameValue2ObjectDictionary(LevelInfo);
2024-05-14 15:29:31 +08:00
2025-04-22 15:39:26 +08:00
foreach (var param in normalParam)
2024-05-14 15:29:31 +08:00
{
2025-04-22 15:39:26 +08:00
levelParam.Add(param.Key, param.Value);
2024-05-14 15:29:31 +08:00
}
2024-10-18 13:47:19 +08:00
_storageEvent.EventList.Add(firstEventName);
2025-04-22 15:39:26 +08:00
// 使用队列模式或者服务未初始化时,暂存事件
if (_useQueueMode || _biService == null)
{
2025-04-22 15:39:26 +08:00
eventQueue.Enqueue((firstEventName, levelParam));
}
2025-04-22 15:39:26 +08:00
else
{
2025-04-22 15:39:26 +08:00
_biService.ReportEvent(firstEventName, levelParam);
}
StorageMgr.Instance.SyncForce = true;
}
catch (Exception e)
{
DebugUtil.LogError("BI Event: {0}, TrackEventLevelOnce Error: {1}", firstEventName, e);
}
}
2024-05-14 15:29:31 +08:00
private bool IsRecorded(string eventName)
{
2024-10-18 13:47:19 +08:00
return _storageEvent.EventList.Contains(eventName);
2024-05-14 15:29:31 +08:00
}
2025-04-22 15:39:26 +08:00
#endregion
2025-03-18 18:40:56 +08:00
2025-04-22 15:39:26 +08:00
#region PHXH 服务器打点
2025-03-18 18:40:56 +08:00
private void TrackEventPhxh(string eventName, Dictionary<string, object> param)
{
2025-04-22 15:39:26 +08:00
if (!_isInit || !sendPhxh)
2025-03-18 18:40:56 +08:00
return;
try
{
2025-04-22 15:39:26 +08:00
string
url = PostHeader.PostUrl + "bi/events"; //"http://bi.kedrgame.com/api/v1/events"; //192.168.2.135:17777
2025-03-18 18:40:56 +08:00
2025-03-18 19:13:40 +08:00
string data = JsonConvert.SerializeObject(param);
2025-03-18 18:40:56 +08:00
var sendData = new PhxhBIEvent();
sendData.event_name = eventName;
2025-03-19 14:05:27 +08:00
sendData.event_key = eventName;
2025-03-20 12:17:42 +08:00
if (param != null)
sendData.event_value = data;
2025-03-18 18:40:56 +08:00
sendData.actor_id = SDKManager.Instance.ApplicationUserID;
2025-03-19 14:05:27 +08:00
sendData.model = deviceInfo;
sendData.uuid = deviceID;
sendData.version = gameVersion;
sendData.platform = platform;
sendData.channel = channel;
2025-03-27 14:40:48 +08:00
Dictionary<string, string> headData = PostHeader.PostHeaderInfo(new Dictionary<string, string>
2025-03-19 14:05:27 +08:00
{
2025-04-22 15:39:26 +08:00
{ "event_name", sendData.event_name }, //string
{ "event_key", sendData.event_key },
{ "event_value", sendData.event_value },
{ "tag", sendData.tag },
{ "game_id", sendData.game_id.ToString() },
{ "actor_id", sendData.actor_id }, //string
{ "details", sendData.details }, //json
{ "uuid", sendData.uuid }, //string
{ "model", sendData.model }, //string
{ "version", sendData.version }, //string
{ "platform", sendData.platform }, //string
{ "channel", sendData.channel }, //string
2025-03-19 14:05:27 +08:00
{ "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() },
});
2025-03-18 18:40:56 +08:00
HttpHelper.PostAsync(url, sendData, headData).Forget();
}
catch (Exception e)
{
DebugUtil.LogError("Track event fail! EventName:" + eventName + ",\n error msg: " + e.Message);
}
}
2025-04-22 15:39:26 +08:00
private class PhxhBIEvent
2025-03-18 18:40:56 +08:00
{
public string event_name; // 标记类型
public string event_key;
public string event_value;
public string actor_id;
public string details;
2025-04-22 15:39:26 +08:00
public string version; // 游戏版本
public string tag; // tag: 区分多游戏
2025-03-18 18:40:56 +08:00
public string platform; // 平台:安卓和IOS
2025-04-22 15:39:26 +08:00
public string model; // 手机型号
public string uuid; // 设备唯一标识
public string channel; // 渠道
2025-03-18 18:40:56 +08:00
public int game_id;
}
2025-04-22 15:39:26 +08:00
#endregion
2024-05-14 15:29:31 +08:00
}