بخش 6 – دستگاه را دنبال کنید

Summarize this content to 400 words in Persian Lang
HMD را دنبال کنید
پوشش به دنبال HMD
کد موقعیت را حذف کنید
ابتدا کد موقعیت مطلقی که در قسمت قبل اضافه کردیم را حذف کنید.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
– var position = new Vector3(0, 2, 3);
– var rotation = Quaternion.Euler(0, 0, 45);
– SetOverlayTransformAbsolute(overlayHandle, position, rotation);
ShowOverlay(overlayHandle);
…
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
شاخص دستگاه
در SteamVR، دستگاه های متصل با Device Index که به طور خودکار از سیستم تخصیص می یابد، شناسایی می شوند. (برای جزئیات، ویکی را بخوانید)برای HMD، به عنوان OpenVR.k_unTrackedDeviceIndex_Hmd تعریف می شود و همیشه 0 است.
موقعیت و چرخش را آماده کنید
اجازه دهید پوشش را در 2 متر جلوتر (محور Z) HMD نمایش دهیم. مانند قسمت قبل اجازه دهید position و rotation متغیرها
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
+ var position = new Vector3(0, 0, 2);
+ var rotation = Quaternion.Euler(0, 0, 0);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
موقعیت نسبی را بر اساس HMD تنظیم کنید
از SetOverlayTransformTrackedDeviceRelative() برای تنظیم موقعیت نسبی بر اساس HMD استفاده کنید. (برای جزئیات، ویکی را بخوانید)
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
+ var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, ref matrix);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception(“Failed to set overlay position: ” + error);
+ }
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
ایندکس دستگاه HMD را پاس کنید (OpenVR.k_unTrackedDeviceIndex_Hmd) و ماتریس تبدیل.برنامه را اجرا کنید و بررسی کنید که پوشش 2 متر جلوتر از HMD نشان داده شده است.
سازماندهی کد
کد موقعیت نسبی را به داخل منتقل کنید SetOverlayTransformRelative().
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
– var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
– var matrix = rigidTransform.ToHmdMatrix34();
– var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, ref matrix);
– if (error != EVROverlayError.None)
– {
– throw new Exception(“Failed to set overlay position: ” + error);
– }
+ SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
…
+ // Pass deviceIndex as argument.
+ private void SetOverlayTransformRelative(ulong handle, uint deviceIndex, Vector3 position, Quaternion rotation)
+ {
+ var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
+ var matrix = rigidTransform.ToHmdMatrix34();
+ var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(handle, deviceIndex, ref matrix);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception(“Failed to set overlay position: ” + error);
+ }
+ }
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
کنترلر را دنبال کنید
پوشش به دنبال کنترلر
از نمایه دستگاه کنترلر به جای HMD استفاده کنید تا همپوشانی از یک کنترلر پیروی کند.
نمایه دستگاه کنترلر را دریافت کنید
فهرست دستگاه کنترلر سمت چپ را با GetTrackedDeviceIndexForControllerRole() از OpenVR.System.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
استدلال این است:کنترلر چپ: EtrackedControllerRole.LeftHandکنترلر سمت راست: EtrackedControllerRole.RightHand
اگر نتوانست نمایه دستگاه را دریافت کند، مثل اینکه کنترلر قطع شده است، GetTrackedDeviceIndexForControllerRole() برمی گرداند k_unTrackedDeviceIndexInvalid.
کنترلر را دنبال کنید
ما نمایه کنترلر چپ را داریم، سپس روکش را به دنبال کنترلر قرار دهیم. ایندکس کنترلر را به SetOverlayTransformRelative() که قبلا برای HMD ایجاد کردیم.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
– SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
مطمئن شوید که کنترلر سمت چپ به پنجره SteamVR متصل است، سپس برنامه را اجرا کنید.
روکش باید به جای HMD از کنترلر پیروی کند.
موقعیت همپوشانی را تنظیم کنید
برای ساخت اپلیکیشن ساعت، موقعیت روکش روی مچ دست چپ را تنظیم می کنیم. پارامترهای موقعیت را در زمان اجرا در ویرایشگر Unity قابل ویرایش کنید.
اضافه کردن متغیرهای عضو
متغیرهای اندازه، موقعیت و چرخش را به عنوان اعضای کلاس اضافه کنید. از ویژگی Range() برای نشان دادن لغزنده در بازرس استفاده کنید.
public class WatchOverlay : MonoBehaviour
{
private ulong overlayHandle = OpenVR.k_ulOverlayHandleInvalid;
+ [Range(0, 0.5f)] public float size = 0.5f;
+ [Range(-0.2f, 0.2f)] public float x;
+ [Range(-0.2f, 0.2f)] public float y;
+ [Range(-0.2f, 0.2f)] public float z;
+ [Range(0, 360)] public int rotationX;
+ [Range(0, 360)] public int rotationY;
+ [Range(0, 360)] public int rotationZ;
…
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
لغزنده ها روی بازرس نشان داده می شوند.
متغیرها را در کد جایگزین کنید
متغیرهای اندازه و موقعیت موجود در کد را با متغیرهای عضو اضافه شده جایگزین کنید.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
– var position = new Vector3(0, 0, 2);
– var rotation = Quaternion.Euler(0, 0, 0);
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
– SetOverlaySize(overlayHandle, 0.5f);
+ SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
اندازه و موقعیت را در Update() به روز کنید
اندازه و موقعیت را در زمان اجرا با افزودن کد به آن قابل ویرایش کنید Update(). توجه داشته باشید که این کد بعدا حذف خواهد شد. برای تعیین موقعیت های جدید و چرخش موقتی است.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var position = new Vector3(x, y, z);
var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
+ private void Update()
+ {
+ SetOverlaySize(overlayHandle, size);
+
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
+ }
…
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
برنامه را اجرا کنید. اطمینان حاصل کنید که نوار لغزنده بازرس اندازه و موقعیت پوشش را در زمان اجرا تغییر می دهد.
موقعیت همپوشانی را تنظیم کنید
لغزنده ها را برای تنظیم موقعیت روکش روی مچ دست چپ حرکت دهید. توصیه می کنم اسلایدرها را از پنجره دسکتاپ که در داشبورد SteamVR باز می شود تغییر دهید.
ویرایشگر Unity را از داشبورد SteamVR کنترل کنید.
راه دیگر نگاه کردن به نمای HMD روی دسکتاپ و تنظیم پارامترها است.
اگر نمی خواهید HMD را بپوشید مفید است.
در اینجا پارامترهای نمونه آورده شده است.
size = 0.08
x = -0.044
y = 0.015
z = -0.131
rotationX = 154
rotationY = 262
rotationZ = 0
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
پس از انجام تنظیمات، روی نام مؤلفه WatchOverlay کلیک راست کرده و Copy Component را انتخاب کنید.
برنامه را متوقف کنید، دوباره روی مؤلفه WatchOverlay کلیک راست کرده و مقادیر کپی شده را با Paste Component Value قرار دهید.
برنامه را اجرا کنید. بررسی کنید که روکش روی مچ دست چپ باشد.
حذف کد موقت
کد را از قسمت حذف کنید Update().
private void Update()
{
– SetOverlaySize(overlayHandle, size);
–
– var position = new Vector3(x, y, z);
– var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
– var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
– if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
– {
– SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
– }
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
هنگامی که کنترلر متصل نیست
در حال حاضر، کنترلر باید هنگام راه اندازی متصل باشد، زیرا ما شاخص دستگاه کنترلر را در قسمت دریافت می کنیم Start().دریافت کد فهرست دستگاه را از Start() to Update() برای پشتیبانی از مواردی که کنترلر در وسط وصل یا قطع می شود.
private void Start()
{
InitOpenVR();
OverlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
– var position = new Vector3(x, y, z);
– var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
– var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
– if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
– {
– SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
– }
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
+ private void Update()
+ {
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
+ }
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
حالا حتی اگر کنترلر از وسط وصل باشد کار می کند.
کد نهایی
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private ulong overlayHandle = OpenVR.k_ulOverlayHandleInvalid;
[Range(0, 0.5f)] public float size;
[Range(-0.2f, 0.2f)] public float x;
[Range(-0.2f, 0.2f)] public float y;
[Range(-0.2f, 0.2f)] public float z;
[Range(0, 360)] public int rotationX;
[Range(0, 360)] public int rotationY;
[Range(0, 360)] public int rotationZ;
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay(“WatchOverlayKey”, “WatchOverlay”);
var filePath = Application.streamingAssetsPath + “/sns-icon.jpg”;
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
private void Update()
{
var position = new Vector3(x, y, z);
var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
}
private void OnApplicationQuit()
{
DestroyOverlay(overlayHandle);
}
private void OnDestroy()
{
ShutdownOpenVR();
}
private void InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception(“Failed to initialize OpenVR: ” + error);
}
}
private void ShutdownOpenVR()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
private ulong CreateOverlay(string key, string name)
{
var handle = OpenVR.k_ulOverlayHandleInvalid;
var error = OpenVR.Overlay.CreateOverlay(key, name, ref handle);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to create overlay: ” + error);
}
return handle;
}
private void DestroyOverlay(ulong handle)
{
if (handle != OpenVR.k_ulOverlayHandleInvalid)
{
var error = OpenVR.Overlay.DestroyOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to dispose overlay: ” + error);
}
}
}
private void SetOverlayFromFile(ulong handle, string path)
{
var error = OpenVR.Overlay.SetOverlayFromFile(handle, path);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to draw image file: ” + error);
}
}
private void ShowOverlay(ulong handle)
{
var error = OpenVR.Overlay.ShowOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to show overlay: ” + error);
}
}
private void SetOverlaySize(ulong handle, float size)
{
var error = OpenVR.Overlay.SetOverlayWidthInMeters(handle, size);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to set overlay size: ” + error);
}
}
private void SetOverlayTransformAbsolute(ulong handle, Vector3 position, Quaternion rotation)
{
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
var error = OpenVR.Overlay.SetOverlayTransformAbsolute(handle, ETrackingUniverseOrigin.TrackingUniverseStanding, ref matrix);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to set overlay position: ” + error);
}
}
private void SetOverlayTransformRelative(ulong handle, uint deviceIndex, Vector3 position, Quaternion rotation)
{
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(handle, deviceIndex, ref matrix);
if (error != EVROverlayError.None)
{
throw new Exception(“Failed to set overlay position: ” + error);
}
}
}
وارد حالت تمام صفحه شوید
از حالت تمام صفحه خارج شوید
در اینجا روکش را روی مچ دست چپ وصل می کنیم. بیایید خروجی دوربین یونیتی را به جای فایل تصویری استاتیک در قسمت بعدی روی همپوشانی بکشیم.
HMD را دنبال کنید
پوشش به دنبال HMD
کد موقعیت را حذف کنید
ابتدا کد موقعیت مطلقی که در قسمت قبل اضافه کردیم را حذف کنید.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
- var position = new Vector3(0, 2, 3);
- var rotation = Quaternion.Euler(0, 0, 45);
- SetOverlayTransformAbsolute(overlayHandle, position, rotation);
ShowOverlay(overlayHandle);
...
شاخص دستگاه
در SteamVR، دستگاه های متصل با Device Index که به طور خودکار از سیستم تخصیص می یابد، شناسایی می شوند. (برای جزئیات، ویکی را بخوانید)
برای HMD، به عنوان OpenVR.k_unTrackedDeviceIndex_Hmd تعریف می شود و همیشه 0 است.
موقعیت و چرخش را آماده کنید
اجازه دهید پوشش را در 2 متر جلوتر (محور Z) HMD نمایش دهیم. مانند قسمت قبل اجازه دهید position
و rotation
متغیرها
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
+ var position = new Vector3(0, 0, 2);
+ var rotation = Quaternion.Euler(0, 0, 0);
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
موقعیت نسبی را بر اساس HMD تنظیم کنید
از SetOverlayTransformTrackedDeviceRelative() برای تنظیم موقعیت نسبی بر اساس HMD استفاده کنید. (برای جزئیات، ویکی را بخوانید)
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
+ var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, ref matrix);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to set overlay position: " + error);
+ }
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
ایندکس دستگاه HMD را پاس کنید (OpenVR.k_unTrackedDeviceIndex_Hmd
) و ماتریس تبدیل.
برنامه را اجرا کنید و بررسی کنید که پوشش 2 متر جلوتر از HMD نشان داده شده است.
سازماندهی کد
کد موقعیت نسبی را به داخل منتقل کنید SetOverlayTransformRelative()
.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
- var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
- var matrix = rigidTransform.ToHmdMatrix34();
- var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, ref matrix);
- if (error != EVROverlayError.None)
- {
- throw new Exception("Failed to set overlay position: " + error);
- }
+ SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
...
+ // Pass deviceIndex as argument.
+ private void SetOverlayTransformRelative(ulong handle, uint deviceIndex, Vector3 position, Quaternion rotation)
+ {
+ var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
+ var matrix = rigidTransform.ToHmdMatrix34();
+ var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(handle, deviceIndex, ref matrix);
+ if (error != EVROverlayError.None)
+ {
+ throw new Exception("Failed to set overlay position: " + error);
+ }
+ }
کنترلر را دنبال کنید
پوشش به دنبال کنترلر
از نمایه دستگاه کنترلر به جای HMD استفاده کنید تا همپوشانی از یک کنترلر پیروی کند.
نمایه دستگاه کنترلر را دریافت کنید
فهرست دستگاه کنترلر سمت چپ را با GetTrackedDeviceIndexForControllerRole() از OpenVR.System
.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
استدلال این است:
کنترلر چپ: EtrackedControllerRole.LeftHand
کنترلر سمت راست: EtrackedControllerRole.RightHand
اگر نتوانست نمایه دستگاه را دریافت کند، مثل اینکه کنترلر قطع شده است، GetTrackedDeviceIndexForControllerRole()
برمی گرداند k_unTrackedDeviceIndexInvalid
.
کنترلر را دنبال کنید
ما نمایه کنترلر چپ را داریم، سپس روکش را به دنبال کنترلر قرار دهیم. ایندکس کنترلر را به SetOverlayTransformRelative()
که قبلا برای HMD ایجاد کردیم.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var position = new Vector3(0, 0, 2);
var rotation = Quaternion.Euler(0, 0, 0);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
- SetOverlayTransformRelative(overlayHandle, OpenVR.k_unTrackedDeviceIndex_Hmd, position, rotation);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, 0.5f);
ShowOverlay(overlayHandle);
}
مطمئن شوید که کنترلر سمت چپ به پنجره SteamVR متصل است، سپس برنامه را اجرا کنید.
روکش باید به جای HMD از کنترلر پیروی کند.
موقعیت همپوشانی را تنظیم کنید
برای ساخت اپلیکیشن ساعت، موقعیت روکش روی مچ دست چپ را تنظیم می کنیم. پارامترهای موقعیت را در زمان اجرا در ویرایشگر Unity قابل ویرایش کنید.
اضافه کردن متغیرهای عضو
متغیرهای اندازه، موقعیت و چرخش را به عنوان اعضای کلاس اضافه کنید. از ویژگی Range() برای نشان دادن لغزنده در بازرس استفاده کنید.
public class WatchOverlay : MonoBehaviour
{
private ulong overlayHandle = OpenVR.k_ulOverlayHandleInvalid;
+ [Range(0, 0.5f)] public float size = 0.5f;
+ [Range(-0.2f, 0.2f)] public float x;
+ [Range(-0.2f, 0.2f)] public float y;
+ [Range(-0.2f, 0.2f)] public float z;
+ [Range(0, 360)] public int rotationX;
+ [Range(0, 360)] public int rotationY;
+ [Range(0, 360)] public int rotationZ;
...
لغزنده ها روی بازرس نشان داده می شوند.
متغیرها را در کد جایگزین کنید
متغیرهای اندازه و موقعیت موجود در کد را با متغیرهای عضو اضافه شده جایگزین کنید.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
- var position = new Vector3(0, 0, 2);
- var rotation = Quaternion.Euler(0, 0, 0);
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
- SetOverlaySize(overlayHandle, 0.5f);
+ SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
اندازه و موقعیت را در Update() به روز کنید
اندازه و موقعیت را در زمان اجرا با افزودن کد به آن قابل ویرایش کنید Update()
. توجه داشته باشید که این کد بعدا حذف خواهد شد. برای تعیین موقعیت های جدید و چرخش موقتی است.
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var position = new Vector3(x, y, z);
var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
+ private void Update()
+ {
+ SetOverlaySize(overlayHandle, size);
+
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
+ }
...
برنامه را اجرا کنید. اطمینان حاصل کنید که نوار لغزنده بازرس اندازه و موقعیت پوشش را در زمان اجرا تغییر می دهد.
موقعیت همپوشانی را تنظیم کنید
لغزنده ها را برای تنظیم موقعیت روکش روی مچ دست چپ حرکت دهید. توصیه می کنم اسلایدرها را از پنجره دسکتاپ که در داشبورد SteamVR باز می شود تغییر دهید.
ویرایشگر Unity را از داشبورد SteamVR کنترل کنید.
راه دیگر نگاه کردن به نمای HMD روی دسکتاپ و تنظیم پارامترها است.
اگر نمی خواهید HMD را بپوشید مفید است.
در اینجا پارامترهای نمونه آورده شده است.
size = 0.08
x = -0.044
y = 0.015
z = -0.131
rotationX = 154
rotationY = 262
rotationZ = 0
پس از انجام تنظیمات، روی نام مؤلفه WatchOverlay کلیک راست کرده و Copy Component را انتخاب کنید.
برنامه را متوقف کنید، دوباره روی مؤلفه WatchOverlay کلیک راست کرده و مقادیر کپی شده را با Paste Component Value قرار دهید.
برنامه را اجرا کنید. بررسی کنید که روکش روی مچ دست چپ باشد.
حذف کد موقت
کد را از قسمت حذف کنید Update()
.
private void Update()
{
- SetOverlaySize(overlayHandle, size);
-
- var position = new Vector3(x, y, z);
- var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
- var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
- if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
- {
- SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
- }
}
هنگامی که کنترلر متصل نیست
در حال حاضر، کنترلر باید هنگام راه اندازی متصل باشد، زیرا ما شاخص دستگاه کنترلر را در قسمت دریافت می کنیم Start()
.
دریافت کد فهرست دستگاه را از Start()
to Update() برای پشتیبانی از مواردی که کنترلر در وسط وصل یا قطع می شود.
private void Start()
{
InitOpenVR();
OverlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
- var position = new Vector3(x, y, z);
- var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
- var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
- if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
- {
- SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
- }
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
+ private void Update()
+ {
+ var position = new Vector3(x, y, z);
+ var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
+ var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
+ if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
+ {
+ SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
+ }
+ }
حالا حتی اگر کنترلر از وسط وصل باشد کار می کند.
کد نهایی
using UnityEngine;
using Valve.VR;
using System;
public class WatchOverlay : MonoBehaviour
{
private ulong overlayHandle = OpenVR.k_ulOverlayHandleInvalid;
[Range(0, 0.5f)] public float size;
[Range(-0.2f, 0.2f)] public float x;
[Range(-0.2f, 0.2f)] public float y;
[Range(-0.2f, 0.2f)] public float z;
[Range(0, 360)] public int rotationX;
[Range(0, 360)] public int rotationY;
[Range(0, 360)] public int rotationZ;
private void Start()
{
InitOpenVR();
overlayHandle = CreateOverlay("WatchOverlayKey", "WatchOverlay");
var filePath = Application.streamingAssetsPath + "/sns-icon.jpg";
SetOverlayFromFile(overlayHandle, filePath);
SetOverlaySize(overlayHandle, size);
ShowOverlay(overlayHandle);
}
private void Update()
{
var position = new Vector3(x, y, z);
var rotation = Quaternion.Euler(rotationX, rotationY, rotationZ);
var leftControllerIndex = OpenVR.System.GetTrackedDeviceIndexForControllerRole(ETrackedControllerRole.LeftHand);
if (leftControllerIndex != OpenVR.k_unTrackedDeviceIndexInvalid)
{
SetOverlayTransformRelative(overlayHandle, leftControllerIndex, position, rotation);
}
}
private void OnApplicationQuit()
{
DestroyOverlay(overlayHandle);
}
private void OnDestroy()
{
ShutdownOpenVR();
}
private void InitOpenVR()
{
if (OpenVR.System != null) return;
var error = EVRInitError.None;
OpenVR.Init(ref error, EVRApplicationType.VRApplication_Overlay);
if (error != EVRInitError.None)
{
throw new Exception("Failed to initialize OpenVR: " + error);
}
}
private void ShutdownOpenVR()
{
if (OpenVR.System != null)
{
OpenVR.Shutdown();
}
}
private ulong CreateOverlay(string key, string name)
{
var handle = OpenVR.k_ulOverlayHandleInvalid;
var error = OpenVR.Overlay.CreateOverlay(key, name, ref handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to create overlay: " + error);
}
return handle;
}
private void DestroyOverlay(ulong handle)
{
if (handle != OpenVR.k_ulOverlayHandleInvalid)
{
var error = OpenVR.Overlay.DestroyOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to dispose overlay: " + error);
}
}
}
private void SetOverlayFromFile(ulong handle, string path)
{
var error = OpenVR.Overlay.SetOverlayFromFile(handle, path);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to draw image file: " + error);
}
}
private void ShowOverlay(ulong handle)
{
var error = OpenVR.Overlay.ShowOverlay(handle);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to show overlay: " + error);
}
}
private void SetOverlaySize(ulong handle, float size)
{
var error = OpenVR.Overlay.SetOverlayWidthInMeters(handle, size);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to set overlay size: " + error);
}
}
private void SetOverlayTransformAbsolute(ulong handle, Vector3 position, Quaternion rotation)
{
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
var error = OpenVR.Overlay.SetOverlayTransformAbsolute(handle, ETrackingUniverseOrigin.TrackingUniverseStanding, ref matrix);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to set overlay position: " + error);
}
}
private void SetOverlayTransformRelative(ulong handle, uint deviceIndex, Vector3 position, Quaternion rotation)
{
var rigidTransform = new SteamVR_Utils.RigidTransform(position, rotation);
var matrix = rigidTransform.ToHmdMatrix34();
var error = OpenVR.Overlay.SetOverlayTransformTrackedDeviceRelative(handle, deviceIndex, ref matrix);
if (error != EVROverlayError.None)
{
throw new Exception("Failed to set overlay position: " + error);
}
}
}
در اینجا روکش را روی مچ دست چپ وصل می کنیم. بیایید خروجی دوربین یونیتی را به جای فایل تصویری استاتیک در قسمت بعدی روی همپوشانی بکشیم.