响应名册与目标变化
订阅共享 Unity 房间中的名册和交互目标事件,并依赖 SDK 保证的事件顺序。
订阅 CharacterAdded, CharacterRemoved, CharacterStatusChanged,以及 InteractionTargetChanged 时自行注册 MultiCharacterRoomSession 在花名册或目标发生变化时立即响应。若你的场景需要在角色进出时更新 UI、日志或游戏状态,而不是轮询花名册,请使用此页。
先决条件
一个已连接的多角色会话。参见 构建你的第一个多角色会话.
对当前项的引用
MultiCharacterRoomSession,来自IConvaiRoomConnectionService.CurrentMultiCharacterSession.
订阅花名册和目标事件
CharacterAdded
Action<CharacterRoomMembership>
在房间已连接之后,又向房间中添加了一个成员。
CharacterRemoved
Action<CharacterRoomMembership>
一个成员已从房间中移除。
CharacterStatusChanged
Action<CharacterRoomMembership>
一个成员身份转变为 就绪 或 失败,或者一个新的成员身份被插入到成员列表中。
InteractionTargetChanged
Action<CharacterRoomMembership, CharacterRoomMembership>
规范的活动成员发生变化;当前成员为 null 当目标被清除时。
using Convai.Runtime.Room;
using UnityEngine;
public class MultiCharacterEventLogger : MonoBehaviour
{
private MultiCharacterRoomSession _session;
public void Attach(MultiCharacterRoomSession session)
{
Detach();
_session = session;
if (_session == null) return;
_session.CharacterAdded += HandleCharacterAdded;
_session.CharacterRemoved += HandleCharacterRemoved;
_session.CharacterStatusChanged += HandleCharacterStatusChanged;
_session.InteractionTargetChanged += HandleInteractionTargetChanged;
}
public void Detach()
{
if (_session == null) return;
_session.CharacterAdded -= HandleCharacterAdded;
_session.CharacterRemoved -= HandleCharacterRemoved;
_session.CharacterStatusChanged -= HandleCharacterStatusChanged;
_session.InteractionTargetChanged -= HandleInteractionTargetChanged;
_session = null;
}
private void HandleCharacterAdded(CharacterRoomMembership membership) =>
Debug.Log($"[MultiCharacter] 已添加 {membership.CharacterId} ({membership.MembershipId})。");
private void HandleCharacterRemoved(CharacterRoomMembership membership) =>
Debug.Log($"[MultiCharacter] 已移除 {membership.CharacterId} ({membership.MembershipId})。");
private void HandleCharacterStatusChanged(CharacterRoomMembership membership) =>
Debug.Log($"[MultiCharacter] {membership.CharacterId} 现在是 {membership.Status}。");
private void HandleInteractionTargetChanged(CharacterRoomMembership previous, CharacterRoomMembership current) =>
Debug.Log($"[MultiCharacter] 目标已从 {previous?.MembershipId ?? "无"} 更改为 {current?.MembershipId ?? "无"}。");
private void OnDestroy() => Detach();
}移除活动角色时的顺序保证
移除当前持有交互目标的成员会按固定顺序触发两个事件: InteractionTargetChanged 会先触发,并将被移除的成员作为 之前 和 null 当前 随后第二个事件触发。响应,以及 CharacterRemoved 的代码 CharacterRemoved 可以依赖在运行时交互目标已经被清除——无需单独检查 ActiveMembershipId 即可避免读取到过期值。
这种“清除目标”的 InteractionTargetChanged 不会推进 RouteEpoch。移除会直接清除 ActiveMembershipId 而不是经过带 epoch 保护的目标更新,因此仅通过比较 RouteEpoch 会错过该事件。此类逻辑应以事件本身为依据,而不是基于 RouteEpoch 变化,如果它还需要响应因移除而清除的目标。
传入替代目标不会抑制第一个事件。SDK 会先应用移除,再应用新目标,因此带有替代项的移除会触发 InteractionTargetChanged 两次:第一次以 null 当前 随后第二个事件触发。响应,然后再以替代成员触发。应将 null 当前目标视为一种过渡状态,而不是终态。
相关的顺序保证同样适用于添加:当插入新成员时, CharacterAdded 会先触发,再触发 CharacterStatusChanged 针对同一成员的该事件。 CharacterAdded 对于给定成员也只会精确触发一次,即使 Convai 的生命周期消息先于花名册更新确认到达也是如此——SDK 会对两条路径去重,而不是触发两次事件。
会话结束时取消订阅
MultiCharacterRoomSession 每次重连时都会被替换,因此附加到某个会话实例上的处理程序在该实例被丢弃后就不再接收事件。请在 OnDisable 或 OnDestroy中解除绑定,并重新绑定到新的 CurrentMultiCharacterSession 在……之后 IConvaiRoomConnectionService.Connected 再次触发。
故障排查
CharacterAdded 从不会为场景初始时就存在的角色触发
这些成员是在创建会话对象时填充的,而不是通过运行时添加代码路径加入的。
阅读 session.Characters 在连接后立即读取,而不要等待 CharacterAdded.
InteractionTargetChanged 以……触发 随后第二个事件触发。响应 当前 null 意外地
持有目标的成员已被移除。无论是否提供替代目标,都会触发此事件。
预期行为。传入 replacementTargetMembershipId 到 在运行时添加和移除角色 这样第二个事件会立即恢复目标,并将 null 视为一种过渡。
下一步
切换交互目标在运行时添加和移除角色角色身份与称呼最后更新于
这有帮助吗?