# ITapBattleEventHandler
# 接口描述
ITapBattleEventHandler是多人联机SDK的事件处理器接口,用于接收SDK的各种异步事件通知。开发者需要实现此接口,并在Initialize时传入实例。
# 接口定义
public interface ITapBattleEventHandler
{
// 连接事件
void OnDisconnected(DisconnectedInfo info);
// 错误事件
void OnBattleServiceError(BattleServiceErrorInfo info);
// 房间属性事件
void OnRoomPropertiesChanged(RoomPropertiesNotification info);
// 玩家属性事件
void OnPlayerCustomPropertiesChanged(PlayerCustomPropertiesNotification info);
void OnPlayerCustomStatusChanged(PlayerCustomStatusNotification info);
// 帧同步事件
void OnFrameSyncStopped(FrameSyncStopInfo info);
void OnFrameReceived(string frameData);
void OnFrameSyncStarted(FrameSyncStartInfo info);
// 玩家事件
void OnPlayerOffline(PlayerOfflineNotification info);
void OnPlayerLeft(LeaveRoomNotification info);
void OnPlayerEntered(EnterRoomNotification info);
// 消息事件
void OnCustomMessageReceived(CustomMessageNotification info);
// 踢人事件
void OnPlayerKicked(PlayerKickedInfo info);
}
# 事件说明
# 连接事件
# OnDisconnected
触发时机:连接断开时
参数:
public class DisconnectedInfo
{
public string reason; // 断开原因
public int code; // 错误代码
}
# 房间事件
# OnPlayerEntered
触发时机:玩家进入房间时
参数:
public class EnterRoomNotification
{
public string roomId; // 房间ID
public PlayerInfo playerInfo; // 进入的玩家信息
}
# OnPlayerLeft
触发时机:玩家离开房间时
参数:
public class LeaveRoomNotification
{
public string roomId; // 房间ID
public string playerId; // 离开的玩家ID
public string playerName; // 离开的玩家名称
}
# OnPlayerKicked
触发时机:玩家被踢出房间时
参数:
public class PlayerKickedInfo
{
public string playerId; // 被踢的玩家ID
public string reason; // 被踢原因
}
# 玩家事件
# OnPlayerOffline
触发时机:玩家掉线时
参数:
public class PlayerOfflineNotification
{
public string playerId; // 掉线的玩家ID
public string playerName; // 掉线的玩家名称
}
# OnPlayerCustomStatusChanged
触发时机:玩家状态变更时
参数:
public class PlayerCustomStatusNotification
{
public string playerId; // 玩家ID
public int status; // 新的自定义状态
}
# OnPlayerCustomPropertiesChanged
触发时机:玩家属性变更时
参数:
public class PlayerCustomPropertiesNotification
{
public string playerId; // 玩家ID
public Dictionary <string, object> properties; // 新的自定义属性(字典)
}
# 房间属性事件
# OnRoomPropertiesChanged
触发时机:房间属性变更时
参数:
public class RoomPropertiesNotification
{
public string id; // 房间ID
public string name; // 房间名称
public Dictionary <string, object> customProperties; // 自定义属性(字典)
}
# 帧同步事件
# OnFrameSyncStarted
触发时机:帧同步开始时
参数:
public class FrameSyncStartInfo
{
public RoomInfo roomInfo; // 房间信息
public int frameSyncId; // 帧同步会话ID,房间内唯一
public int seed; // 随机数种子,用于NewRandomNumberGenerator
public string serverTime; // 服务器时间字符串
}
重要说明:帧同步开始后,使用 info.seed 作为参数调用 TapBattleClient.NewRandomNumberGenerator(info.seed) 创建确定性随机数生成器
# OnFrameReceived
触发时机:接收帧同步数据时(持续触发)
参数:
public class FrameData
{
public int id; // 帧序号
public PlayerInputInfo[] inputs; // 本帧所有玩家的输入
}
public class PlayerInputInfo
{
public string playerId; // 玩家ID
public string data; // 操作数据(JSON字符串)
public string serverTime; // 服务器时间戳
}
使用说明:SDK会自动将JSON反序列化为FrameData对象,可以直接使用
# OnFrameSyncStopped
触发时机:帧同步停止时
参数:
public class FrameSyncStopInfo
{
public string roomId; // 房间ID
public int frameSyncId; // 帧同步会话ID
public int reason; // 停止原因: 0=房主主动结束, 1=超时结束(30分钟)
}
# 消息事件
# OnCustomMessageReceived
触发时机:收到自定义消息时
参数:
public class CustomMessageNotification
{
public string fromPlayerId; // 消息发送者玩家ID
public object message; // 自定义消息内容
public int type; // 消息类型(0-房间内所有玩家,1-队伍内所有玩家)
}
# 错误事件
# OnBattleServiceError
触发时机:多人联机服务发生错误时
参数:
public class BattleServiceErrorInfo
{
public string errorMessage; // 错误消息
public int errorCode; // 错误代码
}
# 实现示例
# 示例1:基础实现
using UnityEngine;
public class MyBattleEventHandler : ITapBattleEventHandler
{
private RandomNumberGenerator rng; // 随机数生成器实例
public void OnDisconnected(DisconnectedInfo info)
{
Debug.Log($"连接断开: {info.reason} (代码: {info.code})");
}
public void OnPlayerEntered(EnterRoomNotification info)
{
Debug.Log($"玩家 {info.playerInfo.id} 进入房间");
}
public void OnPlayerLeft(LeaveRoomNotification info)
{
Debug.Log($"玩家 {info.playerId} 离开房间");
}
public void OnPlayerKicked(PlayerKickedInfo info)
{
Debug.Log($"玩家 {info.playerId} 被踢出房间,原因: {info.reason}");
}
public void OnPlayerOffline(PlayerOfflineNotification info)
{
Debug.Log($"玩家 {info.playerId} ({info.playerName}) 掉线");
}
public void OnPlayerCustomStatusChanged(PlayerCustomStatusNotification info)
{
Debug.Log($"玩家 {info.playerId} 状态变更: {info.status}");
}
public void OnPlayerCustomPropertiesChanged(PlayerCustomPropertiesNotification info)
{
Debug.Log($"玩家 {info.playerId} 属性变更");
}
public void OnRoomPropertiesChanged(RoomPropertiesNotification info)
{
Debug.Log($"房间 {info.id} 属性变更");
}
public void OnFrameSyncStarted(FrameSyncStartInfo info)
{
Debug.Log($"帧同步开始");
Debug.Log($" 房间: {info.roomInfo.id}");
Debug.Log($" 帧同步ID: {info.frameSyncId}");
Debug.Log($" 随机种子: {info.seed}");
Debug.Log($" 服务器时间: {info.serverTime}");
// 创建确定性随机数生成器(新API - 返回实例)
rng = TapBattleClient.NewRandomNumberGenerator(info.seed);
}
public void OnFrameReceived(FrameData frameData)
{
// 直接使用帧数据对象
Debug.Log($"收到第 {frameData.id} 帧,包含 {frameData.inputs.Length} 个输入");
foreach (var input in frameData.inputs)
{
ProcessPlayerInput(input.playerId, input.data);
}
// 使用确定性随机数
if (rng != null)
{
int randomValue = rng.RandomInt();
// 使用randomValue进行游戏逻辑...
}
}
public void OnFrameSyncStopped(FrameSyncStopInfo info)
{
Debug.Log($"帧同步停止");
Debug.Log($" 房间: {info.roomId}");
Debug.Log($" 帧同步ID: {info.frameSyncId}");
Debug.Log($" 停止原因: {info.reason}");
// 释放随机数生成器(新API - 使用实例方法)
if (rng != null)
{
rng.Free();
rng = null;
}
}
public void OnCustomMessageReceived(CustomMessageNotification info)
{
Debug.Log($"收到来自 {info.fromPlayerId} 的消息");
}
public void OnBattleServiceError(BattleServiceErrorInfo info)
{
Debug.LogError($"多人联机服务错误: {info.errorMessage} (代码: {info.errorCode})");
}
private void ProcessPlayerInput(string playerId, string data) { }
}
# 最佳实践
- 实现所有方法 - 即使某些事件不需要处理,也建议添加日志以便调试
- 错误处理 - 务必实现OnBattleServiceError,及时处理服务异常
- UI更新 - 事件回调在主线程执行,可以安全地更新UI
- 状态同步 - 使用事件更新本地的游戏状态和UI显示
- 避免阻塞 - 事件处理方法中不要执行耗时操作
# 相关API
- TapBattleClient.Initialize - 初始化时传入事件处理器
