# unity-vr-base **Repository Path**: gagahappy/unity-vr-base ## Basic Information - **Project Name**: unity-vr-base - **Description**: Unity VR 基础设置 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-08-12 - **Last Updated**: 2023-02-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Unity 2021.3.8 VR 空项目 VR空项目, 直接拷贝出来, 改项目名称就可以 ## 软件版本: - Unity 2021.3.8flc1 - XR Interaction Toolkit 2.1.1 - PICO Unity Integration SDK v211 : Packages/PICO UnityXR Integration SDK v211 目录下 - Oculus 未安装 - HTC Vive 未安装 - ## Unity 配置 ### 发布设置: Oculus建议将纹理压缩改为ASTC ### Build Settings 项目设置: #### Player 玩家 ```json 颜色控件 : 线性 自动图形API : 关闭 Active Input Handling 输入管理器 : 两个Both (为搜狗输入法) ``` ### 字体 \Assets\TextMesh Pro\Fonts 文件夹下 msyh.ttf : 微软雅黑 zh-cn.txt : 中文字库 Window→TextMeshPro→Font Asset Creator 字符集选txt, 尺寸8192, 方式SDFAA,点击Generate Font Atlas 完成Save ### 输入法 搜狗 VR 键盘 https://t7bkgg7632.feishu.cn/drive/home/ [UnityXR_SogouKeyboard.unitypackage](https://bytedance.feishu.cn/file/boxcnGbL4q8ihfhzmfEheAl6Ejc) [Unity XR SougouKeyboard Package 集成指南](https://bytedance.feishu.cn/docx/doxcnQx4ulMAx2BQgbfMkOGd0ld) 搜狗 VR 键盘仅适用于发布到中国大陆的应用程序。 目前仅支持使用inputFiled(Legacy),并不支持InputField (TMP)。 ## XR Interaction Toolkit: - Device : 简单的使用, 定制化低 - Action : XR的输入特征值定义为行为,然后将这个行为指定给交互组件, 趋势(OpenXR只支持Action) #### XR Origin(VR) VR摄像机+两个射线手柄对象 - Origin Base Game Object:根节点,射线移动和转移就是修改这个对象的位置 - Camera Floor Offset Object:设置的gameObject包含VR相机, 调整可修改相机相对位置 - Tracking Origin Mode:原点空间跟踪模式(PICO不能选NotSpecified) - Not Specified - Device 设备 : 表示设备相对跟踪原点。设备相对跟踪原点定义了在某个先前时间点(通常在重新居中事件、开机或 AR/VR 会话开始时)位于空间内设备位置的本地原点。设备提供的姿势数据将在此空间中相对于本地原点。这意味着在此模式下返回的姿势将不包括用户高度(对于 VR)或设备高度(对于 AR),并需要相应地手动偏移 XR 设备的摄像机跟踪位置。 - Camera Y Offset : 可以设置相机高度 - Floor : 0.0.0位于地板上或XR设备确定表面 #### XR Interaction Manager 交互管理类, **XR Origin(VR)**添加会自动添加 #### Tracked Pose Driver - Device:跟踪设备类型 - PoseSource:追踪资源,大部分选择Center - TrackingType:姿态跟踪类型,分位置和朝向 - UpdateType:刷新类型,选择UpdateAndBeforeRender,能提供最顺滑的姿态追踪和最低时延的设备延迟 #### Tracked Pose Driver (Input System) 添加XR Origin(VR) 的时候会被自动添加到XR Origin(VR) /Camera Offset/Main Camera 下 #### XR Controller (Action-based) XR Origin(VR) 会被自动添加到XR Origin(VR) /Camera Offset/LeftHand Controller 和 RightHand Controller 下 从XR输入子系统将跟踪的输入控制器设备上的特征值解释为XR交互状态,例如Select。此外,它将被跟踪设备的当前姿态值应用于(支持多个XRController,如左手可同时有一个Ray和一个Direct交互控制器,这样可以实现复杂交互,但小心交互者间层级设定) - 追踪 - UpdateTrackingType:刷新类型 UpdateAndBeforeRender 更新 BeforeRender - PositionAction - RotationAction - TrackingStateAction - 输入 - SelectAction - SelectActionValue - ActivateAction - 模型 - ModelPrefab:手模预制物,可以自动生成 - ModelParent:手模父节点 - Model:手模Tnf - AnimateModel:动画模块 #### XR Socket Interactor 通过插座定位可交互内容的交互者 - InteractionLayerMask:交互层级遮罩,指定可交互的层级 - AttachTransform:附加对象 - Keep Selected Target Valid:在最初选择一个可交互对象后,即使它不再是有效的目标,也是否继续选择它。(不勾选,抓取的物品要一直保持选中状态,否则就会掉落) - Show Interactable Hover Meshes:当交互对象悬停在插座上时,是否显示网格 - Socket Active:是否激活插座 - Recycle Delay Time:设置移除对象后插座拒绝悬停的时间 #### XR Ray Interactor 带有射线的手柄模板对象(添加XR Origin(VR) 会自动添加左右手) - Interaction Layer Mask:交互层级遮罩,指定可交互的层级 - Enable Interaction With UI GameObject:交互器是否能影响UI - Force Grab:是否将抓取物品拉到手上 - Anchor Control - Attach Transform:附加对象, 转换被用作可交互对象的附加点。将创建一个空的游戏对象。 - Ray Origin Transform:射线原点,朝向也是调它, 任何光线投射的起始位置和方向。如果没有在启动时设置,它将根据AttachTransform自动创建。 - Raycast Configuration - 直线类型 : - Straight Line : 直线 - Projectile Curve : 抛物线 - Bezier Curve : 贝塞尔曲线 - Max Raycast Distance 修改距离 - Raycast Mask:射线可交互的层级,Unity自带的层级类,不勾选的层级,射线会穿透它 - Hit Closest Only:是否只交互最近碰撞的物品 - AudioEvent:添加触发声音片段 - HapticEvents:添加触发震动 - InteractorEvents:添加交互事件 #### XR Direct Interactor 交互器用于直接与接触的交互设备进行交互。这是通过更新此交互器的当前有效目标集的触发器卷来处理的。这个组件必须有一个被设置为触发器的碰撞卷才能工作。 不具有射线的手柄模板对象, 需要添加碰撞盒去拿东西 - SelectActionTrigger:对控制器输入进行定义,如何确定为select - KeepSelectedTargetVailid:当选择一个可交互目标后,即使他不再是有效的目标,仍然能选择他 - Hide Controller On Select:选择状态下是否隐藏控制器 - Allow Hovered Activate:是否允许悬浮情况下激活 #### XR Simple Interactable 最简单的交互对象,只是有一个具体的交互实现,一般用在去对交互事件进行相应,没有实际的交互手段。 - Interaction Layer Mask:层掩码允许与交互层掩码与该交互层掩码中的任何层重叠的交互者进行交互。 - Custom Reticle:有效时出现在射线尾端的十字线。 - Select Mode:是否运行多个交互者和交互对象进行交互 #### XR Grab Interactable 允许基本“抓取”功能的可交互组件。可以连接到一个选择的交互者,并在遵守物理的同时跟随它(并在释放时继承速度) 组件添加后变为手柄可抓取物(包含上面的射线和非射线) 必须有碰撞盒(Collider)进行检测, 建议带刚体Rigibody抓取投掷 - Interaction Layer Mask : 匹配Layer - Custom Reticle:有效时出现在射线尾端的十字线 - Select Mode:是否运行多个交互者和交互对象进行交互 - Movement Type 运动类型:移动方式选择(如果想让抓取物品保持物理属性,不穿透墙和桌子,这里要选择“速度追踪”) - Retain Transform Parent:交互者放下物品后是否还原至原父对象下 - Track Positon:是否追踪交互者的位置 - Track Rotation:是否追踪交互者的方向 - Throw On Detach:抛出, 释放时继承交互者的速度 - Throw Smoothing Duration : 抛出平滑持续时间 - Throw Smoothing Curve : - Throw Velocity Scale : 抛出速度比例 - Throw Angular Velocity Scale : 抛出角速度比例 - Force Gravity On Detach:是否强制对象释放时拥有重力 - Attach Transform:交互时依附的点(默认设置物品的中心) - Use Dvnamic Attach : Enable to make the effective attachment pointbased on the pose of the lnteractor when theselection is made.在进行选择时,可以根据输入者的姿势制作有效的附件点 - Match Position : (选中时)匹配位置,在初始化抓取时,匹配接触器的攻击点的位置。这将超越附加变换的位置。 - Match Rotation : (选中时)匹配旋转,在初始化抓取时,匹配交互器攻击点的旋转,这将超过附加变换的旋转。 - Attach Point Compatibility Mode - Default (Recommended) : 附加点兼容性模式默认(推荐)可插入事件 - Legacy (Obsolete) : 遗产(过时) - Interactable Events : 抓取事件, 如抓取物体,释放物体,抓取物体后按下Trigger键 #### XR UI Canvas 创建Canvas只有在此Canvas下的UI组件才能和手柄射线产生正常的交互 (射线长度为30m) Canvas Scaler - Dynamic Pixels Per Unit : 每个单位的动态像素 - Reference Pixels Per Unit : 检查射线是否被3D遮挡 Unit Tracked Device Graphic Raycaster - Check For 2D Occlusion : 检查射线是否被2D遮挡 - Check For 3D Occlusion : 检查射线是否被3D遮挡 - Raycast Trigger Interaction : 检查3D遮挡时光线投射是否应该击中Triggers - Use Global - 忽略 - Collide : 碰撞 #### Locomotion System 行走,跑动画自动适应地形。全方向,全地形。 控制对XR Origin的访问。这个系统强制在同一时间只有一个移动供应商可以移动XR原点。这是访问XR Origin受控制的唯一地方,不推荐使用多个LocomotionSystem实例驱动单个XR Origin #### Teleportation Area / Teleportation Anchor 地面传导移动(Anchor 传送固定点),射线检测到可传送地面后射线变色,默认按下 Trigger 键实现传送 - Interaction Layer Mask : 匹配Layer - Custom Reticle:有效时射线尾端的的标志对象 - Select Mode:是否运行多个交互者和交互对象进行交互 - Teleport Anchor Transform:传送目的地的位点 - Teleportation Configuration - Match Orientation : 隐形传态构形匹配方向, 定位origin的方式选择 - Teleport Trigger : 传送端触发器, 传送触发的时间选择 - Teleportation Provider : 隐形传态提供者, 该远程传送可交互的远程传送提供者将远程传送请求传送 #### Teleportion Provider 传送管理类 #### Snap Turn Provider 转身管理类 - Turn Amount:每次捕捉到信号旋转的值 - Debounce Time : - Enable Turn Left Right : - Enable Turn Around - Delay Time #### Continuous Turn Provider 连续旋转提供者 - Turn Speed:旋转速度 - Input Binding:旋转轴绑定 - Controllers:控制器设置 - Deadzone Min/Max:能否触发功能的最大值最小值 #### Continuous Move Provider - Move Speed:移动速度 - Forward Source:自定义向前的方向 - Input Binding:移动轴绑定 - Controllers:控制器设置 - Deadzone Min/Max:能否触发功能的最大值最小值 ```js Input System Ul Actions Point Action Left Click Action Middle Click Action Right Click Action Scroll Wheel Action Navigate Action Submit Action Cancel Action ``` ## XR 第三人称绑定 Character Controller 第三人称类 Character Controller Driver 控制移动上面的脚本, 不过转身好像不能移动, 需要修改, 继承后在update()里运行UpdateCharacterController(), 使Character Controller实时更新 ```C# using UnityEngine.XR.Interaction.Toolkit; public class CharacterControllerDriverUpdate : CharacterControllerDriver { void Update() { UpdateCharacterController() } } ``` ## PICO 配置: - **Preview Tool(类似于 Oculus 的 linked)** 参考Pico官方文档, 目前连上设备休眠或Unity停止运行后会出问题, 需要设备重启 - **版权提示/权限校验** 菜单栏→PXR_SDK→平台设置, 将User Entitlement Check关闭, 或**Entitlement Check Simulation**√上, 在**Device SN**里填写VR设备序列表, 用安卓adb.exe可以获取 ## Oculus 配置: https://blog.csdn.net/m0_60290598/article/details/123521029 可以去官网下载, 在包管理器安装 Oculus Integration 34, 导入 **OVRPlayController** : 拖如场景就可以移动, 设置手柄模型 OVRPlayController→OVRCameraRig→TrackingSpace里的 LeftControllerAnchor下拖入CustomHandLeft 和 RightControllerAnchor下拖入CustomHandRight 在 Core/CustomHands/Models下, 拳头握不住修改动画Layers的ThumbLayer的Blending 为 Additive模式, 最终需要在代码里改 OVRControllerPrefab : 就是射线 **OVR Grabber** : 抓取,默认 CustomHandLeft / Right 带 **OVR Grabbable** : 添加到物体, 表示物体可以被抓, 也需要添加 Rigidbody **OVR Raycaster** : UI 手柄交互, Canvas调到World Space UIHelpers : Oculus→SampleFramework→Core→DebugUI→Prefabs→UIHelpers, 拖入, 会出现二个EventSystem,把外面的删除 **Locomotion Controller** **Locomotion Teleport** : 移动的时候的光标(可能) **Teleport Input Handler Touch** **Teleport Target Handler Physical** Teleport Aim Handler Laser : 线, 激光 Teleport Aim Handler Visual Parabolic: 线, 抛物线 Teleport Aim Handler Visual Laser : 线 Teleport Aim Visual Laser : 渲染线对象 传送方式 Teleport Transition Blink Teleport Transition Instant Teleport Transition Warp Teleport Orlentation Handler Thumbatick 旋转 ## 其他: - Android Debug Bridge(ADB) : [Windows](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) [macOS](https://dl.google.com/android/repository/platform-tools-latest-darwin.zip) [Linux](https://dl.google.com/android/repository/platform-tools-latest-linux.zip) - [Pico Metrics Tool 1.2.0](https://developer-cn.pico-interactive.com/sdk?deviceId=1&platformId=1&itemId=15) 性能监控, 打开, 开启后会实时监控 - [CurvedUI (曲面UI)](https://blog.csdn.net/u014361280/article/details/108451217) Unity 可以将平面的UI拉伸成曲面效果 - LuBan 数据 : 运行先安装[dotNet SDK 6.0](https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0)\ ```shell # Allow unsafe code in Player Settings to fix this error : 错误 # Edit → Project Settings → Player → 搜索 'unsafe' 然后勾上 # 安装 # luban_examples\Projects\Csharp_Unity_bin_or_json\Assets\LubanLib → \Assets\Plugins\Luban\LubanLib # 安装工具库 # luban_examples\Tools\Luban.ClientServer → \Plugins\Luban\Tools # luban_examples\MiniTemplate → \Plugins\Luban # luban_examples\Projects\Csharp_Unity_bin_or_json 里的bat和sh复制到 \Plugins\Luban ``` - [HybridCLR](https://focus-creative-games.github.io/hybridclr/) 热更新 : ```shell # 安装(粗鲁的方式) 从 gitee https://gitee.com/focus-creative-games/hybridclr_unity.git clone 到本地, 然后复制到 Packages 目录下 # 菜单 HybridCLR/Installer... # Unity 2021 IOS 打包需要覆盖Unity文件 将文件 {package目录}/Data~/ModifiedUnityAssemblies/2021.3.x/UnityEditor.CoreModule-{Win,Mac}.dll 覆盖到 {Editor安装目录}/Editor/Data/Managed/UnityEngine/UnityEditor.CoreModule.dll dll 制作方法 : https://focus-creative-games.github.io/hybridclr/modify_unity_dll/ ``` - Asset Bundle Browser ## URP 渲染管线 - 在 Unity Package 里下载 URP 包 或按循序安装如下包 Core RP Library : com.unity.render-pipelines.core 这个找不到 : com.unity.render-pipelines.shadergraph Universal RP : com.unity.render-pipelines.universal - 用 URP 替换内置渲染管线, 在Assets 下创建 Create → Readering → URP Asset (with Universal Renderer) - Project Settings → Graphics → Sciptable Render Pipeline Settings → 选中刚才的 Asset URP渲染管线 - URP Asset (with 2D Renderer) - URP Asset (with Universal Renderer) - URP Renderer Feature - URP 2D Renderer - URP Universal Renderer - URP Global Settings Asset - URP Post-process Data - URP XR System Data - Environment Library (Look Dev) [XR 中的通用渲染管线兼容性](https://docs.unity.cn/cn/current/Manual/xr-render-pipeline-compatibility.html) ### Pico Metrics Tool 翻译 - GPU Utilization (GPU U) GPU利用率 - CPU Utilization (CPU U) CPU利用率 - FPS - GPU Temperature GPU温度 - CPU Temerature - Singlepass - Foveation Level (FRL) 眼压水平 - Eye Buffer Width (EBW) 眼缓冲宽度 - Eye Buffer Height (EBH) 眼球缓冲高度 - Used Memory (U MEM) 使用内存 - Available Memory (A MEM) 可用内存 - GPU Level - CPU Level - Battery Level (BAT) 电池电量 - Battery Temperature (BTEM) 电池温度 - Power Voltage (POW V) 电源电压 - Stale Frame Count (STALE) - App GPU Time(APP T) - Early Frame Count (EARLY) - TimeWarp GPU Time (TW T) - Guardian GPU Time - Display Refresh Rate (DRR) 显示刷新率 ```C# UnityEngine.XR.CommonUsages // Informs to the developer whether the device is currently being tracked. isTracked = ("IsTracked"); // The primary face button being pressed on a device, or sole button if only one is available. primaryButton = ("PrimaryButton"); // The primary face button being touched on a device. primaryTouch = ("PrimaryTouch"); // The secondary face button being pressed on a device. secondaryButton = ("SecondaryButton"); // The secondary face button being touched on a device. secondaryTouch = ("SecondaryTouch"); // 设备按下 Grip Button 捏合键 gripButton = ("GripButton"); // 按下 TriggerButton 扳机键 triggerButton = ("TriggerButton"); // 按下 MenuButton 菜单键, 用于暂停、返回或退出游戏 menuButton = ("MenuButton"); // Represents the primary 2D axis being clicked or otherwise depressed. primary2DAxisClick = ("Primary2DAxisClick"); // Represents the primary 2D axis being touched. primary2DAxisTouch = ("Primary2DAxisTouch"); // Represents the secondary 2D axis being clicked or otherwise depressed. secondary2DAxisClick = ("Secondary2DAxisClick"); // Represents the secondary 2D axis being touched. secondary2DAxisTouch = ("Secondary2DAxisTouch"); // Use this property to test whether the user is currently wearing and/or interacting // with the XR device. The exact behavior of this property varies with each type // of device: some devices have a sensor specifically to detect user proximity, // however you can reasonably infer that a user is present with the device when // the property is UserPresenceState.Present. userPresence = ("UserPresence"); // Represents the values being tracked for this device. trackingState = ("TrackingState"); // Value representing the current battery life of this device. batteryLevel = ("BatteryLevel"); // A trigger-like control, pressed with the index finger.用食指按下的类似触发器的控件。 trigger = ("Trigger"); // Represents the users grip on the controller.表示用户对控制器的抓地力。 grip = ("Grip"); // The primary touchpad or joystick on a device. primary2DAxis = ("Primary2DAxis"); // A secondary touchpad or joystick on a device. secondary2DAxis = ("Secondary2DAxis"); // 设备的位置 devicePosition = ("DevicePosition"); // 左眼在设备上的位置 leftEyePosition = ("LeftEyePosition"); // 右眼在设备上的位置 rightEyePosition = ("RightEyePosition"); // The position of the center eye on this device. centerEyePosition = ("CenterEyePosition"); // The position of the color camera on this device. colorCameraPosition = ("CameraPosition"); // The velocity of the device. deviceVelocity = ("DeviceVelocity"); // The angular velocity of this device, formatted as euler angles. deviceAngularVelocity = ("DeviceAngularVelocity"); // The velocity of the left eye on this device. leftEyeVelocity = ("LeftEyeVelocity"); // The angular velocity of the left eye on this device, formatted as euler angles. leftEyeAngularVelocity = ("LeftEyeAngularVelocity"); // The velocity of the right eye on this device. rightEyeVelocity = ("RightEyeVelocity"); // The angular velocity of the right eye on this device, formatted as euler angles. rightEyeAngularVelocity = ("RightEyeAngularVelocity"); // The velocity of the center eye on this device. centerEyeVelocity = ("CenterEyeVelocity"); // The angular velocity of the center eye on this device, formatted as euler angles. centerEyeAngularVelocity = ("CenterEyeAngularVelocity"); // The velocity of the color camera on this device. colorCameraVelocity = ("CameraVelocity"); // The angular velocity of the color camera on this device, formatted as euler angles. colorCameraAngularVelocity = ("CameraAngularVelocity"); // The acceleration of the device. deviceAcceleration = ("DeviceAcceleration"); // The angular acceleration of this device, formatted as euler angles. deviceAngularAcceleration = ("DeviceAngularAcceleration"); // The acceleration of the left eye on this device. leftEyeAcceleration = ("LeftEyeAcceleration"); // The angular acceleration of the left eye on this device, formatted as euler angles. leftEyeAngularAcceleration = ("LeftEyeAngularAcceleration"); // The acceleration of the right eye on this device.右眼在这个装置上的加速度。 rightEyeAcceleration = ("RightEyeAcceleration"); // The angular acceleration of the right eye on this device, formatted as euler angles. rightEyeAngularAcceleration = ("RightEyeAngularAcceleration"); // The acceleration of the center eye on this device. centerEyeAcceleration = ("CenterEyeAcceleration"); // The angular acceleration of the center eye on this device, formatted as euler angles. centerEyeAngularAcceleration = ("CenterEyeAngularAcceleration"); // The acceleration of the color camera on this device. colorCameraAcceleration = ("CameraAcceleration"); // The angular acceleration of the color camera on this device, formatted as euler angles. colorCameraAngularAcceleration = ("CameraAngularAcceleration"); // 设备的旋转角度 deviceRotation = ("DeviceRotation"); // The rotation of the left eye on this device. leftEyeRotation = ("LeftEyeRotation"); // The rotation of the right eye on this device. rightEyeRotation = ("RightEyeRotation"); // The rotation of the center eye on this device. centerEyeRotation = ("CenterEyeRotation"); // The rotation of the color camera on this device. colorCameraRotation = ("CameraRotation"); // Value representing the hand data for this device. handData = ("HandData"); // An Eyes struct containing eye tracking data collected from the device. eyesData = ("EyesData"); // A non-handed 2D axis. [Obsolete("CommonUsages.dPad is not used by any XR platform and will be removed.")] dPad = ("DPad"); // Represents the grip pressure or angle of the index finger. [Obsolete("CommonUsages.indexFinger is not used by any XR platform and will be removed.")] indexFinger = ("IndexFinger"); // Represents the grip pressure or angle of the middle finger. [Obsolete("CommonUsages.MiddleFinger is not used by any XR platform and will be removed.")] middleFinger = ("MiddleFinger"); // Represents the grip pressure or angle of the ring finger. [Obsolete("CommonUsages.RingFinger is not used by any XR platform and will be removed.")] ringFinger = ("RingFinger"); // Represents the grip pressure or angle of the pinky finger. [Obsolete("CommonUsages.PinkyFinger is not used by any XR platform and will be removed.")] pinkyFinger = ("PinkyFinger"); // Represents a thumbrest or light thumb touch. [Obsolete("CommonUsages.thumbrest is Oculus only, and is being moved to their package. Please use OculusUsages.thumbrest. These will still function until removed.")] thumbrest = ("Thumbrest"); // Represents a touch of the trigger or index finger. [Obsolete("CommonUsages.indexTouch is Oculus only, and is being moved to their package. Please use OculusUsages.indexTouch. These will still function until removed.")] indexTouch = ("IndexTouch"); // Represents the thumb pressing any input or feature. [Obsolete("CommonUsages.thumbTouch is Oculus only, and is being moved to their package. Please use OculusUsages.thumbTouch. These will still function until removed.")] thumbTouch = ("ThumbTouch"); ```