MetaWorld 虚拟世界
  • iOS : Objective-C
  • Android
  • 产品简介
  • 下载
  • 快速开始
    • 跑通示例源码
    • 集成 MetaWorld SDK
    • 设置 License 鉴权
    • 实现 MetaWorld 基本场景
  • 基础能力
  • 客户端 API
  • 常见错误码
  • 常见问题
  • 文档中心
  • MetaWorld 虚拟世界
  • 基础能力
  • 房间管理

房间管理

更新时间:2023-02-20 16:05

组件简介

房间是 ZEGO MetaWorld SDK 的基础概念,承载了虚拟世界需要的所有元素,包括场景资源、角色资源以及 UI 资源(例如:摇杆控件)等。

MetaWorld SDK 使用 Room 类来管理房间,Room 类具备以下功能:

  • 进入房间:进入房间时,加载房间需要的各类资源(包括场景资源、角色资源以及相关的 UI 资源)。
  • 退出房间:退出房间时,销毁创建的资源,防止内存泄漏。
  • 其它能力:查询进房角色、获取当前角色 ZMWGameObject 等功能,不同的 Room 提供的能力有差异。

前提条件

在实现“房间管理”功能之前,请确保:MetaWorld SDK 已经初始化(initWithConfig)成功。

开发者需要调用接口 initWithConfig 启动 ZegoMetaWorldService,并通过 addServiceObserver 监听 ZegoMetaWorldService 初始化是否成功。

使用步骤

使用 房间管理 功能前,需要先创建 Room 对象。

id<ZMWBaseRoom> room = (id<ZMWBaseRoom>)[self.rootGameObject addComponent:@"ZMWBaseRoom"];

同一时间,同一用户只能创建和使用一个 Room。如果需要进入其它 Room,则必须先调用 leave 接口离开并销毁当前的 Room。

MetaWorld SDK 提供两种类型的 Room:ZMWBaseRoom 房间ZMWStateSyncedRoom 房间,请参考下文的具体介绍。

ZMWBaseRoom 房间

ZMWBaseRoom 指单机版房间,具备进入和退出房间、以及进房成功后获取当前房间和角色的 ZMWGameObject 能力。适用于用户之间无需互动的场景,例如博物馆游览、私人影院等。

开发者拿到 ZMWGameObject 后,可以向房间和角色模型上添加、获取、删除各个组件,调用各组件的接口,使用各组件能力。

1. 进入房间

  1. 开发者通过 addServiceObserver 监听 ZegoMetaWorldService 初始化成功状态。
  2. 确定初始化成功后,调用 startEnterRoom 接口加载 Room。
  3. 调用 enter 接口进入 MetaWorld 房间。
  4. 进房成功后,需要调用 getComponentInChildren 接口获取 ZMWCameraCaptureComponent 组件;然后调用 attachCamera 接口,通过该组件把房间 3D 画面渲染到 ZegoMetaWorldView 上。
[[ZegoMetaWorldService sharedInstance] addServiceObserver:self];
#pragma mark MetaWorldServiceDelegate
/** ZegoMetaWorldService错误回调*/
- (void)onError:(ZegoMetaWorldErrorCode)code desc:(NSString *)desc{
}

/** ZegoMetaWorldService状态回调*/
- (void)onStateChange:(MetaWorldServiceState)state{
    if (state == MetaWorld_InitSucceed) {
        id<ZMWGameObject> rootGameObject = [[ZegoMetaWorldService sharedInstance] getRoot];
        [self startEnterRoom:rootGameObject];
    }
}
-(void)startEnterRoom:(id<ZMWGameObject>)rootGameObject{
    ZMWLogI(@"SceneLoad", @"MetaWorldScene,onUnitySceneLoad rootGameObject uid=%d", [rootGameObject getUid]);
    self.rootGameObject = rootGameObject;
    self.metaWorldRoom = (id<ZMWBaseRoom>)[self.rootGameObject addComponent:@"ZMWBaseRoom"];


    __weak typeof(self) weakSelf = self;
    [self.metaWorldRoom setCharacterCreatedListener:^(NSString *userID, id<ZMWGameObject> roleObj) {
    }];

    int nRoomId = [self.rtcRoomId intValue];
    int mwRoomId = [self.MWRoomId intValue];
    int  roomId = nRoomId * 100 + mwRoomId; //房间id可以根据业务情况设定

    [self.metaWorldRoom setRoomConfig:roomId
                          rtcUserID:self.rtcUserId
                        rtcUserName:self.rtcUserName
                             vistor:NO];
    [self.metaWorldRoom enter:@"ZegoLandKTV" characterResID:@"FemaleBody" birthPosition:nil progressCallback:^(float progress) {

        } resultCallback:^(int ec, id<ZMWGameObject> roomObj) {
            ZMWLogI(@"enterRoom",@"enterRoom resultCallBack ec=%d",ec);
            if(ec != 0){
                return;
            }
            [weakSelf attachMetaWorldView:self.metaWroldView];
        }];
}
-(void)attachMetaWorldView:(ZegoMetaWorldView*)view{
    id<ZMWGameObject> roomGameObject = self.rootGameObject;

    NSLog(@"attachMetaWorldView roomGameObject: %d", roomGameObject.getUid);
    NSAssert(roomGameObject != nil, @"room gameobject 不能为空");
    id<ZMWCameraCaptureComponent> cameraCaptureCom = (id<ZMWCameraCaptureComponent>)[roomGameObject getComponentInChildren::@"ZMWCameraCaptureComponent"];

    [view attachCamera:cameraCaptureCom];
}

2. 使用组件(进房成功后)

进入房间成功后,开发者可以获取到“房间”或“角色”的 ZMWGameObject,并分别向房间和角色模型上添加、获取、删除各个组件,调用各组件的接口,使用各组件能力。

例如:用户获取到自己的角色 ZMWGameObject 之后,通过 getComponentInChildren 接口,获取 ZMWCharacterController 角色控制器对象。最后通过调用 playAnimation 接口,传入动画 ID,即可播放动画。

-(void)playAnimation:(id<ZMWBaseRoom>)room {
    id<ZMWGameObject> roleObject = [room getCurrentCharacterObject];
    id<ZMWCharacterController> characterController;
    if (roleObject) {
        characterController = (id<ZMWCharacterController>)[roleObject getComponentInChildren:@"ZMWCharacterController"];
    }
    [characterController playAnimation:@"101" autoIdle:YES callback:^(int result) {
        ZMWLogI(@"CharacterController", @"playAnimation complete result=%d", result);
    }];
}

3. 退出房间

  1. 调用 detachCamera 接口,取消和房间画面的关联。
  2. 调用 leave 接口,离开当前 MetaWorld 房间。
-(void)leave{
    [self.metaWroldView detachCamera];
    [self.metaWroldView removeFromSuperview];
    self.metaWroldView = nil;

    [self.metaWorldRoom leave];
    [[ZegoMetaWorldService sharedInstance] removeServiceObserver:self];
}

ZMWStateSyncedRoom 房间

ZMWStateSyncedRoom 指联机版房间,不仅具备了 ZMWBaseRoom 房间 的所有能力,同时扩展了账号体系、以及状态同步功能。适用于 KTV、直播间等多个用户之间互动的场景。

1. 进入房间

  1. 开发者通过 addServiceObserver 监听 ZegoMetaWorldService 初始化成功状态。
  2. 确定初始化成功后,调用 startEnterRoom 接口加载 Room。
  3. 在进入房间前,先通过 setRoomConfig 接口,设置房间相关的房间号、角色账号等信息。
  4. 调用 enter 接口进入 MetaWorld 房间。
  5. 进房成功后,需要调用 getComponentInChildren 接口获取 ZMWCameraCaptureComponent 组件;然后调用 attachCamera 接口,通过该组件把房间 3D 画面渲染到 ZegoMetaWorldView 上。

调用 setRoomConfig 接口传入的信息(RoomID、UserID、UserName),需要和 Express SDK 保持一致,即如果用户在 App 内使用 Express SDK 的其它能力(如推拉流等),MetaWorld SDK 的接口传值信息,需要保持一致,否则会进房失败。

[[ZegoMetaWorldService sharedInstance] addServiceObserver:self];
#pragma mark MetaWorldServiceDelegate
/** ZegoMetaWorldService 错误回调*/
- (void)onError:(ZegoMetaWorldErrorCode)code desc:(NSString *)desc{
}

/** ZegoMetaWorldService 状态回调*/
- (void)onStateChange:(MetaWorldServiceState)state{
    if (state == MetaWorld_InitSucceed) {
        id<ZMWGameObject> rootGameObject = [[ZegoMetaWorldService sharedInstance] getRoot];
        [self startEnterRoom:rootGameObject];
    }
}
-(void)startEnterRoom:(id<ZMWGameObject>)rootGameObject{
    ZMWLogI(@"SceneLoad", @"MetaWorldScene,onUnitySceneLoad rootGameObject uid=%d", [rootGameObject getUid]);
    self.rootGameObject = rootGameObject;
    self.metaWorldRoom = (id<ZMWStateSyncedRoom>)[self.rootGameObject addComponent:@"ZMWStateSyncedRoom"];


    __weak typeof(self) weakSelf = self;
    [self.metaWorldRoom setCharacterCreatedListener:^(NSString *userID, id<ZMWGameObject> roleObj) {
    }];

    int nRoomId = [self.rtcRoomId intValue];
    int mwRoomId = [self.MWRoomId intValue];
    int  roomId = nRoomId * 100 + mwRoomId; //房间 ID 可以根据业务情况设定

    [self.metaWorldRoom setRoomConfig:roomId
                          rtcUserID:self.rtcUserId
                        rtcUserName:self.rtcUserName
                             vistor:NO];
    [self.metaWorldRoom enter:@"ZegoLandKTV" characterResID:@"FemaleBody" birthPosition:nil progressCallback:^(float progress) {

        } resultCallback:^(int ec, id<ZMWGameObject> roomObj) {
            ZMWLogI(@"enterRoom",@"enterRoom resultCallBack ec=%d",ec);
            if(ec != 0){
                return;
            }
            [weakSelf attachMetaWorldView:self.metaWroldView];
        }];
}
-(void)attachMetaWorldView:(ZegoMetaWorldView*)view{
    id<ZMWGameObject> roomGameObject = self.rootGameObject;

    NSLog(@"attachMetaWorldView roomGameObject: %d", roomGameObject.getUid);
    NSAssert(roomGameObject != nil, @"room gameobject 不能为空");
    id<ZMWCameraCaptureComponent> cameraCaptureCom = (id<ZMWCameraCaptureComponent>)[roomGameObject getComponentInChildren::@"ZMWCameraCaptureComponent"];

    [view attachCamera:cameraCaptureCom];
}

进入相同房间(同一个 RoomID)的角色,会处于同一个房间内,且用户能够看到彼此;同时,ZMWStateSyncedRoom 具备的状态同步功能,也会同步每个用户的角色模型状态,包括进退房状态、实时位置信息、动画状态等信息。

例如,如果某个角色在房间内奔跑,则该房间内的其他用户都能实时看到该角色的动作及位置变化。

2. 使用组件(进房成功后)

进入房间成功后,开发者可以获取到“房间”或“角色”的 ZMWGameObject,并分别向房间和角色模型上添加、获取、删除各个组件,调用各组件的接口,使用各组件能力。

例如:用户获取到自己的角色 ZMWGameObject 之后,通过 addComponent 接口,绑定角色名牌组件 ZMWCharacterExtension。绑定成功后,调用 setResourceIDsetCharacterName 等接口,控制名牌组件的显示内容、UI 样式等。

-(void)initCharacterExtension(id<ZMWStateSyncedRoom>)room {
    [room setCharacterCreatedListener:^(NSString *userID, id<ZMWGameObject> roleObject) {
        id<ZMWCharacterExtension> characterExtension = (id<ZMWCharacterExtension>)[roleObject getComponentInChildren:@"ZMWCharacterExtension"];
        [characterExtension setCharacterName:userID];
    }];
}

3. 退出房间

  1. 调用 detachCamera 接口,取消和房间画面的关联。
  2. 调用 leave 接口,离开当前 MetaWorld 房间。
-(void)leave{
    [self.metaWroldView detachCamera];
    [self.metaWroldView removeFromSuperview];
    self.metaWroldView = nil;

    [self.metaWorldRoom leave];
    [[ZegoMetaWorldService sharedInstance] removeServiceObserver:self];
}
本篇目录