# TapBattleClient.SendCustomMessage

# 功能描述

发送自定义消息给房间内玩家。可用于状态同步、房间频道消息、表情、道具赠送等场景。与UpdateRoomProperties共享每秒15次的调用频率限制。

# 方法签名

public static void SendCustomMessage(SendCustomMessageOption option)

# 参数说明

参数名 类型 必填 说明
data SendCustomMessageData 消息数据
success Action<TapCallbackResult> 发送成功回调
fail Action<TapCallbackResult> 发送失败回调

# SendCustomMessageData

字段名 类型 必填 说明
msg string 自定义消息内容(utf8字符串,最大2048字节)
type int 接收者类型:0=房间内所有玩家(不包括发送者),1=发送给指定玩家
receivers string[] 接收方玩家ID列表(当type==1时有效,最多20个ID)

# 使用说明

# 应用场景

用于房间内玩家之间的自定义数据交互,使用灵活,适用于大多数场景:

  • 状态同步 - 回合制游戏的操作同步(如棋牌、卡牌游戏)
  • 房间通信 - 聊天消息、表情互动、道具赠送
  • 游戏事件 - 触发特效、播放动画、同步游戏状态

# 注意事项

  • 频率限制 - 与UpdateRoomProperties共享每秒15次的调用频率限制
  • 字符限制 - 消息内容最大2048字节
  • 房间内可用 - 必须在房间内才能发送
  • 状态同步核心API - 适合用于回合制游戏的状态同步,相比帧同步更轻量高效

# 代码示例

# 示例1:发送房间频道消息

using UnityEngine;
using UnityEngine.UI;

public class RoomMessageController : MonoBehaviour
{
    [SerializeField] private InputField messageInput;

    public void SendRoomMessage()
    {
        string message = messageInput.text;
        if (string.IsNullOrEmpty(message)) return;

        TapBattleClient.SendCustomMessage(new SendCustomMessageOption
        {
            data = new SendCustomMessageData
            {
                msg = message,
                type = 0 // 发送给房间内其他玩家
            },
            success = (result) => {
                Debug.Log("房间消息发送成功");
                messageInput.text = "";
            },
            fail = (result) => {
                Debug.LogError($"消息发送失败: {result.errMsg}");
            }
        });
    }

    // 收到自定义消息
    public void OnCustomMessageReceived(CustomMessageNotification info)
    {
        Debug.Log($"收到玩家 {info.player_id} 的房间消息: {info.msg}");
        DisplayRoomMessage(info.player_id, info.msg);
    }

    private void DisplayRoomMessage(string playerId, string message) { }
}

# 示例2:发送表情

using UnityEngine;

public class EmoteController : MonoBehaviour
{
    public void SendEmote(int emoteId)
    {
        var emoteData = new {
            type = "emote",
            emoteId = emoteId,
            timestamp = System.DateTimeOffset.Now.ToUnixTimeMilliseconds()
        };

        TapBattleClient.SendCustomMessage(new SendCustomMessageOption
        {
            data = new SendCustomMessageData
            {
                msg = JsonUtility.ToJson(emoteData),
                type = 0
            }
        });
    }

    public void OnCustomMessageReceived(CustomMessageNotification info)
    {
        var data = JsonUtility.FromJson<EmoteData>(info.msg);
        if (data.type == "emote") {
            ShowEmote(info.player_id, data.emoteId);
        }
    }

    [System.Serializable]
    class EmoteData {
        public string type;
        public int emoteId;
        public long timestamp;
    }

    private void ShowEmote(string playerId, int emoteId) { }
}

# 示例3:游戏操作数据

using UnityEngine;

public class GameController : MonoBehaviour
{
    // 发送游戏操作(如落子、出牌、移动等)
    public void SendGameAction(string actionType, object actionData)
    {
        var message = new {
            type = actionType,
            data = actionData,
            timestamp = System.DateTimeOffset.Now.ToUnixTimeMilliseconds()
        };

        TapBattleClient.SendCustomMessage(new SendCustomMessageOption
        {
            data = new SendCustomMessageData
            {
                msg = JsonUtility.ToJson(message),
                type = 0  // 发送给房间内所有玩家
            }
        });
    }

    // 接收并处理游戏操作
    public void OnCustomMessageReceived(CustomMessageInfo info)
    {
        var message = JsonUtility.FromJson<GameMessage>(info.message.ToString());
        
        // 根据消息类型处理不同的游戏逻辑
        switch (message.type) {
            case "move":
                ApplyMove(message.data);
                break;
            case "play_card":
                ApplyCard(message.data);
                break;
        }
    }

    private void ApplyMove(object data) { /* 应用移动操作 */ }
    private void ApplyCard(object data) { /* 应用出牌操作 */ }
}