Rokid Air AR 眼镜 && Cocos Creator XR 开发笔记

白玉无冰

共 5539字,需浏览 12分钟

 · 2022-10-26

9b1ef349297b8c71b4664959f33ae84a.webp

开发前准备

硬件设备

Rokid Air 眼镜:

https://air.rokid.com/

支持进入AR模式的 Android 手机:

https://air.rokid.com/userguide

b9b57fcacc577956954341f8413e01a4.webp

软件

Rokid Air App :

在Rokid Air app 1.9.1版本上有部分不兼容问题,请确认不要使用此版本的Rokid Air app进行调试和发布,之前的版本和1.9.2或以后的版本将不受影响;

直接从官网上下载,各大应用市场可能更新有滞后。
https://air.rokid.com/download
55af6e7dcf8393176aae850feebfa247.webp

Cocos Creator 3.6.1

https://www.cocos.com/creator

安装配置安卓环境

https://docs.cocos.com/creator/manual/zh/editor/publish/setup-native-development.html

XR 插件:

https://store.cocos.com/app/detail/4117

投屏(可选

adb tcpip + scrcpy

Rokid AIR 投屏方案(Win):https://ivb750bbcz.feishu.cn/docs/doccniMDevcb6lgto0DzXPEn8Xe

Rokid AIR 投屏方案(Mac):https://ivb750bbcz.feishu.cn/docs/doccndTeu2iDmQt7a2fSJqnpLvg


Hello World

新建VR模版

8d300daa4b20fe9ce7680da45f54f658.webp

打开 xr_main 场景,可以看到相机是挂在 XR HMD 这个节点下
4e0b5b7a4cb98f5e827e1a06f8729673.webp

场景空空,有点孤单,可以随意添加一些3d物体,调节成你喜欢的角度和位置,确保在相机视野内。

baaeec399be95e3a56d42ef0557e57bc.webp

构建发布

在菜单栏选择 项目->构建发布,发布平台选择 XR Rokid Air,第一次发布还需填上包名。首次构建可能会慢点,后面再构建就会更快了。
9b0f6cf863ceb3507405b294f3f1eec6.webp

如果出现异常的话,一般来说是安卓环境相关配置有异常,可以查看构建日志定位问题。
855a14b64142385c435a5a545edc0cc1.webp

打开 {当面项目}/build/xr-rokid/publish/release ,将包安装到手机上。
9c0370e793a0c3dac9f3c0df525f8b43.webp

效果预览

安装应用后,直接打开是这样的
f0e5bbe4704291a4940102ed1d281e2d.webp

需要接上AR眼镜,在 Rokid Air App 中进入 AR 模式。

1095604338c9d342f9b864a68aae84ef.webp

在其应用库可以找到刚才安装好的包。

f8e28d485e21a00f17b5a6ad95cffef6.webp

打开后,晃动脑袋,可以看到我们之前添加的物体
52eb1e0af6a86d7616ecc70a2408483c.webp

此时手机上显示的是游戏手柄

6442184234f04b705fc3f2a27a3c3d70.webp

目前的资源包参考如下
helloworld.zip (24.2 KB)


输入事件

手柄输入事件

为了更好的控制游戏,需要知道手机中的手柄事件。

6442184234f04b705fc3f2a27a3c3d70.webp

Cocos Creator 中的监听事件代码如下:

    input.on(Input.EventType.GAMEPAD_INPUT, this._gamepadEvent, this);

获取手柄输入参数如下

    private _gamepadEvent(event: EventGamepad) {
const gamepad = event.gamepad;
}

gamepad 的成员可以在 cc.d.ts中看到。

b7c7a4cb7c7ba30dcc892fc3bb6c0843.webp

可以简单写个脚本,验证摇杆参数返回。

    import { _decorator, Component, input, Input, EventGamepad, Vec2, Label } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('GamepadEventTest')
export class GamepadEventTest extends Component {
@property(Label)
lb_leftStickValue: Label = null!

@property(Label)
lb_rightStickValue: Label = null!

start() {
input.on(Input.EventType.GAMEPAD_INPUT, this._gamepadEvent, this);
}

private _gamepadEvent(event: EventGamepad) {
const gamepad = event.gamepad;
const leftStickValue = gamepad.leftStick.getValue() as Vec2;
this.lb_leftStickValue.string = `${leftStickValue.toString()}`;

const rightStickValue = gamepad.rightStick.getValue() as Vec2;
this.lb_rightStickValue.string = `${rightStickValue.toString()}`;
}
}

并在场景中加入label节点验证输出。

b305b5dedc1d8b73db4f4e8a5d66fac3.webp

重新打包后预览效果,可以看出摇杆的输出结果

4f566a0fb58091446dfa9e0220c5b56d.webp

资源包如下:

helloworld-gamepad-event-test.zip (194.1 KB)

头戴显示器姿态输入事件

这个事件可以获取到眼镜的一些重要参数,如旋转角度,在定制眼镜交互时可能会用到。

813e112f471560de14623a13852459cd.webp

Cocos Creator 中的监听事件代码如下:

    input.on(Input.EventType.HMD_POSE_INPUT, this._dispatchEventHMDPose, this);

获取输入参数如下

    private _dispatchEventHMDPose(eventHMD: EventHMD) {
const hmdInputDevice = eventHMD.hmdInputDevice;
}

4ff6fdc95d586df2d11d463f62945dad.webp

相关的逻辑可以参考插件中的代码 extensions/xr-plugin/assets/xr/component/device/pose-tracker.ts

c0501ee78bffb2d6a938d78ddeab9f5e.webp

simple-shooting

将现有的游戏移植到 Rokid Air 眼镜,用的是 cocos-example-projects/simple-games/assets/simple-shooting 这个demo

7bcc2422af642787349ad6f6650a157c.webp

下载好工程后,找到主场景,导出资源包。

6ce4c3b76dfd5c8ba6045b5c1a827ea8.webp

这里已经导出了资源包,如下所示:

链接: https://pan.baidu.com/s/1VRZyn3gAWF0Y6vsYdImFmg?pwd=6qce 提取码: 6qce 复制这段内容后打开百度网盘手机App,操作更方便哦

再导入到helloworld 中03749cd16f65db808175cfe7f1cfd4ee.webp

切换到shooting game 的场景中,找到主相机,转成 XR HMD

238aabee8d8e96faa8b56b7de2dbcba7.webp

构建参数选择当前新的场景

a3114f81c7288ef2bedb1d0040fd3f56.webp

链接眼镜,打开应用后,效果如下图所示:b06d020c32baf2db16b698dd59168e27.webp

剩下的问题就是调整参数,接入输入事件,修改脚本assets/simple-shooting/scripts/ShootingPlayerController.ts 核心参考代码如下:

            //input.on(Input.EventType.GAMEPAD_INPUT, this._gamepadEvent, this);
//input.on(Input.EventType.HMD_POSE_INPUT, this._dispatchEventHMDPose, this);

private _dispatchEventHMDPose(eventHMD: EventHMD) {
const hmdInputDevice = eventHMD.hmdInputDevice;

const _quatPose:Quat = hmdInputDevice.headMiddleOrientation.getValue();
_quatPose.getEulerAngles(tempVec3_a);

const horizontalRot = this.node.getRotation();
horizontalRot.getEulerAngles(tempVec3_b);
tempVec3_b.y = tempVec3_a.y;
this.node.setRotationFromEuler(tempVec3_b);

if (-tempVec3_a.x > this.viewDownAngle && -tempVec3_a.x < this.viewUpAngle) {
const verticalRot = this.verticalViewNode.getRotation();
verticalRot.getEulerAngles(tempVec3_b);
tempVec3_b.x = -tempVec3_a.x;
this.verticalViewNode.setRotationFromEuler(tempVec3_b);
}
}

aValue = false;
bValue = false;
private _gamepadEvent(event: EventGamepad) {
const gamepad = event.gamepad;
const leftStickValue = gamepad.leftStick.getValue() as Vec2;
if(this._velocity.z !=leftStickValue.y && this._velocity.x!=-leftStickValue.x){
this._velocity.z = leftStickValue.y;
this._velocity.x = -leftStickValue.x;
if(leftStickValue.lengthSqr()>0){
this.changeToAnimState(PlayerAnimState.Running);
}else{
this.checkToIdle();
}
}

if (gamepad.buttonSouth.getValue() === 1 && !this.aValue) {
this.aValue = true;
this.doAction(ActionType.Shoot,true)
} else if (gamepad.buttonSouth.getValue() === 0) {
this.aValue = false;
}
if (gamepad.buttonEast.getValue() === 1 && !this.bValue) {
this.bValue = true;
this.doAction(ActionType.ThrowGrenade,true)
} else if (gamepad.buttonEast.getValue() === 0) {
this.bValue = false;
}
}


放上文章开头接入的资源包供大家参考学习

链接: https://pan.baidu.com/s/1dpvvTppaPFyvGqRzsyWEIA?pwd=3q68 提取码: 3q68 复制这段内容后打开百度网盘手机App,操作更方便哦

小结

b视频: https://www.bilibili.com/video/BV1bt4y1u7CS/

相关资源链接与讨论见论坛:https://forum.cocos.org/t/topic/141564  (阅读原文直达)


点击 阅读原文”跳转至论坛讨论

“点赞“ ”在看” 鼓励一下75c7626428d95f27c15d70749da28597.webp

浏览 56
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报