Pointer — MRTK2
Artikel ini menjelaskan cara mengonfigurasi dan menanggapi input Pointer dalam praktiknya. Untuk lebih memahami cara mengontrol beberapa pointer pada tingkat tinggi, lihat Arsitektur Pointer.
Pointer diinstansikan secara otomatis saat runtime ketika pengontrol baru terdeteksi. Lebih dari satu pointer dapat dilampirkan ke pengontrol. Misalnya, dengan profil penunjuk default, pengontrol Windows Mixed Reality mendapatkan garis dan penunjuk parabola untuk pemilihan normal dan teleportasi masing-masing.
Konfigurasi penunjuk
Pointer dikonfigurasi sebagai bagian dari Sistem Input di MRTK melalui MixedRealityPointerProfile
. Jenis profil ini ditetapkan ke MixedRealityInputSystemProfile
di pemeriksa Konfigurasi MRTK. Profil Pointer menentukan kursor, jenis Pointer yang tersedia saat runtime, dan bagaimana pointer tersebut berkomunikasi satu sama lain untuk memutuskan mana yang aktif.
Jangkauan Penunjuk - Menentukan jarak maksimum tempat Pointer dapat berinteraksi dengan GameObject.
Menunjuk Masker Lapisan Raycast - Ini adalah array LayerMasks yang diprioritaskan untuk menentukan kemungkinan GameObjects mana pun yang dapat berinteraksi dengan Pointer tertentu dan urutan interaksi untuk dicoba. Ini mungkin berguna untuk memastikan Pointer berinteraksi dengan elemen UI terlebih dahulu sebelum objek adegan lainnya.
Konfigurasi opsi penunjuk
Konfigurasi Profil Pointer MRTK default mencakup kelas penunjuk berikut dan prefab terkait di luar kotak. Daftar penunjuk yang tersedia untuk sistem saat runtime ditentukan di bawah Opsi Penunjuk di profil Pointer. Pengembang dapat menggunakan daftar ini untuk mengonfigurasi ulang Pointer yang ada, menambahkan Pointer baru, atau menghapusnya.
Setiap entri Pointer ditentukan oleh kumpulan data berikut:
Jenis Pengontrol - Kumpulan pengontrol yang valid untuk penunjuk.
- Misalnya, PokePointer bertanggung jawab untuk "menusuk" objek dengan jari, dan secara default ditandai sebagai hanya mendukung jenis pengontrol tangan artikulasi. Pointer hanya dibuat ketika pengontrol tersedia dan khususnya Jenis Pengontrol menentukan pengontrol apa yang dapat dibuat dengan prefab pointer ini.
Handedness - memungkinkan penunjuk hanya dibuat untuk tangan tertentu (kiri/kanan)
Catatan
Mengatur properti Handedness dari entri Pointer ke None akan secara efektif menonaktifkannya dari sistem sebagai alternatif untuk menghapus Pointer tersebut dari daftar.
- Prefab Pointer - Aset prefab ini akan dibuat ketika pengontrol yang cocok dengan jenis pengontrol dan keserangan yang ditentukan mulai dilacak.
Dimungkinkan untuk memiliki beberapa pointer yang terkait dengan pengontrol. Misalnya, dalam DefaultHoloLens2InputSystemProfile
(Aset/MRTK/SDK/Profil/HoloLens2/) pengontrol tangan artikulasi dikaitkan dengan PokePointer, GrabPointer, dan DefaultControllerPointer (yaitu sinar tangan).
Catatan
MRTK menyediakan serangkaian prefab pointer di Aset/MRTK/SDK/Features/UX/Prefabs/Pointers. Prefab kustom baru dapat dibangun selama berisi salah satu skrip pointer di Aset/MRTK/SDK/Features/UX/Scripts/Pointers atau skrip lain yang mengimplementasikan IMixedRealityPointer
.
Konfigurasi kursor
Kursor Tatapan dapat dikonfigurasi secara langsung melalui GazeCursorPrefab
properti di MixedRealityInputSystemProfile
dalam Editor. Untuk mengonfigurasi kursor yang digunakan untuk pointer lain, Anda perlu mengubah prefab yang digunakan di CursorPrefab
bidang yang sesuai BaseControllerPointer
. Untuk mengubah kursor secara terprogram, ubah BaseCursor
properti pada perilaku yang IMixedRealityPointer
sesuai.
Lihat prefab kursor kami di Aset/MRTK/SDK/Fitur/UX/Prefabs/Kursor misalnya implementasi perilaku kursor. Secara khusus, DefaultGazeCursor memberikan implementasi yang kuat untuk mengubah grafik kursor berdasarkan status kontekstual.
Kelas penunjuk default
Kelas berikut adalah pointer MRTK out-of-box yang tersedia dan ditentukan dalam Profil Pointer MRTK default yang diuraikan di atas. Setiap prefab pointer yang disediakan di bawah Aset/MRTK/SDK/Features/UX/Prefabs/Pointers berisi salah satu komponen pointer yang terpasang.
Penunjuk jauh
LinePointer
LinePointer, kelas penunjuk dasar, menggambar garis dari sumber input (yaitu pengontrol) ke arah penunjuk dan mendukung satu transmisi sinar ke arah ini. Umumnya, kelas anak-anak seperti ShellHandRayPointer
dan pointer teleportasi dibuat dan digunakan (yang juga menggambar garis untuk menunjukkan di mana teleportasi akan berakhir di) alih-alih kelas ini yang terutama menyediakan fungsionalitas umum.
Untuk pengontrol gerakan seperti di Oculus, Vive, dan Windows Mixed Reality, rotasi akan cocok dengan rotasi pengontrol. Untuk pengontrol lain seperti tangan artikulasi HoloLens 2, rotasi cocok dengan pose penunjuk tangan yang disediakan sistem.
CurvePointer
CurvePointer memperluas kelas LinePointer dengan memungkinkan transmisi sinar multi-langkah di sepanjang kurva. Kelas penunjuk dasar ini berguna untuk instans melengkung seperti penunjuk teleportasi di mana garis secara konsisten membungkuk ke dalam parabola.
ShellHandRayPointer
Implementasi ShellHandRayPointer, yang meluas dari LinePointer
, digunakan sebagai default untuk Profil Pointer MRTK. Prefab DefaultControllerPointer mengimplementasikan ShellHandRayPointer
kelas .
GGVPointer
Juga dikenal sebagai penunjuk Tatapan/Gerakan/Suara (GGV ), GGVPointer mendukung interaksi tampilan dan ketuk gaya HoloLens 1, terutama melalui Tatapan dan Ketukan Udara atau Tatapan dan interaksi Pilih suara. Posisi dan arah penunjuk GGV didorong oleh posisi dan rotasi kepala.
TouchPointer
TouchPointer bertanggung jawab untuk bekerja dengan input Unity Touch (yaitu layar sentuh). Ini adalah 'interaksi jauh' karena tindakan menyentuh layar akan mentransmisikan sinar dari kamera ke lokasi yang berpotensi jauh di adegan.
MousePointer
MousePointer mendukung raycast layar ke dunia untuk interaksi yang jauh, tetapi untuk mouse alih-alih sentuhan.
Catatan
Dukungan mouse tidak tersedia secara default di MRTK tetapi dapat diaktifkan dengan menambahkan Penyedia Data Input baru jenis MouseDeviceManager
ke profil input MRTK dan menetapkan MixedRealityMouseInputProfile
ke penyedia data.
Penunjuk dekat
PokePointer
PokePointer digunakan untuk berinteraksi dengan objek game yang mendukung "interaksi dekat yang dapat disentuh." yang merupakan GameObjects yang memiliki skrip terlampir NearInteractionTouchable
. Dalam kasus UnityUI, pointer ini mencari NearInteractionTouchableUnityUIs. PokePointer menggunakan SphereCast untuk menentukan elemen terdekat yang dapat disentuh dan digunakan untuk memberi daya seperti tombol yang dapat ditekan.
Saat mengonfigurasi GameObject dengan NearInteractionTouchable
komponen, pastikan untuk mengonfigurasi parameter localForward untuk mengarahkan keluar dari bagian depan tombol atau objek lain yang harus dibuat dapat disentuh. Pastikan juga bahwa batas yang dapat disentuh cocok dengan batas objek yang dapat disentuh.
Properti Poke Pointer yang berguna:
- TouchableDistance: Jarak maksimum di mana permukaan yang dapat disentuh dapat berinteraksi dengan
- Visual: Objek game yang digunakan untuk merender visual ujung jari (cincin di jari, secara default).
- Garis: Garis opsional untuk menggambar dari ujung jari ke permukaan input aktif.
- Poke Layer Masks - Array LayerMasks yang diprioritaskan untuk menentukan kemungkinan GameObjects mana yang dapat berinteraksi dengan pointer dan urutan interaksi untuk dicoba. Perhatikan bahwa GameObject juga harus memiliki
NearInteractionTouchable
komponen untuk berinteraksi dengan pointer poke.
SpherePointer
SpherePointer menggunakan UnityEngine.Physics.OverlapSphere untuk mengidentifikasi objek terdekat NearInteractionGrabbable
untuk interaksi, yang berguna untuk input "dapat diambil" seperti ManipulationHandler
. Mirip PokePointer
/NearInteractionTouchable
dengan pasangan fungsi, agar dapat berinteraksi dengan Sphere Pointer, objek game harus berisi komponen yang merupakan NearInteractionGrabbable
skrip.
Properti Sphere Pointer yang Berguna:
- Sphere Cast Radius: Radius untuk bola yang digunakan untuk mengkueri objek yang dapat diambil.
- Dekat Margin Objek: Jarak di atas Sphere Cast Radius untuk dikueri untuk mendeteksi apakah objek berada di dekat penunjuk. Total radius deteksi Objek Dekat adalah Sphere Cast Radius + Near Object Margin
- Dekat Sudut Sektor Objek: Sudut di sekitar sumbu maju penunjuk untuk kueri objek terdekat.
IsNearObject
Membuat fungsi kueri seperti kerujut. Ini diatur ke 66 derajat secara default untuk mencocokkan perilaku Hololens 2
- Dekat Object Smoothing Factor: Faktor smoothing untuk deteksi Near Object. Jika objek terdeteksi di Radius Objek Dekat, radius yang dikueri kemudian menjadi Near Object Radius * (1 + Near Object Smoothing Factor) untuk mengurangi sensitivitas dan mempersulit objek untuk meninggalkan rentang deteksi.
- Grab Layer Masks - Array LayerMasks yang diprioritaskan untuk menentukan kemungkinan GameObjects mana yang dapat berinteraksi dengan penunjuk dan urutan interaksi untuk dicoba. Perhatikan bahwa GameObject juga harus memiliki
NearInteractionGrabbable
untuk berinteraksi dengan SpherePointer.Catatan
Lapisan Kesadaran Spasial dinonaktifkan dalam prefab GrabPointer default yang disediakan oleh MRTK. Ini dilakukan untuk mengurangi dampak performa melakukan kueri tumpang tindih bola dengan jala spasial. Anda dapat mengaktifkan ini dengan memodifikasi prefab GrabPointer.
- Abaikan Colliders Tidak di FOV - Apakah akan mengabaikan collider yang mungkin berada di dekat pointer, tetapi tidak benar-benar dalam visual FOV. Ini dapat mencegah penangkapan yang tidak disengaja, dan akan memungkinkan sinar tangan menyala ketika Anda mungkin berada di dekat grabbable tetapi tidak dapat melihatnya. Visual FOV didefinisikan melalui kerucut alih-alih frustum khas karena alasan performa. Kerucut ini berpusat dan berorientasi sama dengan frustum kamera dengan radius sama dengan tinggi layar setengah (atau FOV vertikal).
Penunjuk teleport
TeleportPointer
akan menaikkan permintaan teleportasi ketika tindakan diambil (yaitu tombol teleportasi ditekan) untuk memindahkan pengguna.ParabolicTeleportPointer
akan menaikkan permintaan teleportasi ketika tindakan diambil (yaitu tombol teleportasi ditekan) dengan raycast garis parabolik untuk memindahkan pengguna.
Dukungan pointer untuk platform realitas campuran
Tabel berikut merinci jenis penunjuk yang biasanya digunakan untuk platform umum di MRTK. CATATAN: Dimungkinkan untuk menambahkan berbagai jenis pointer ke platform ini. Misalnya, Anda dapat menambahkan penunjuk Poke atau penunjuk Sphere ke VR. Selain itu, perangkat VR dengan gamepad dapat menggunakan pointer GGV.
Penunjuk | OpenVR | Realitas Campuran Windows | HoloLens 1 | HoloLens 2 |
---|---|---|---|---|
ShellHandRayPointer | Valid | Valid | Valid | |
TeleportPointer | Valid | Valid | ||
GGVPointer | Valid | |||
SpherePointer | Valid | |||
PokePointer | Valid |
Interaksi pointer melalui kode
Antarmuka peristiwa penunjuk
MonoBehaviours yang mengimplementasikan satu atau beberapa antarmuka berikut dan ditetapkan ke GameObject dengan Collider
akan menerima peristiwa interaksi Pointer seperti yang didefinisikan oleh antarmuka terkait.
Kejadian | Deskripsi | Penghandel |
---|---|---|
Sebelum Fokus Berubah / Fokus Berubah | Dinaikkan pada objek permainan kehilangan fokus dan yang mendapatkannya setiap kali pointer mengubah fokus. | IMixedRealityFocusChangedHandler |
Fokus Masukkan / Keluar | Dimunculkan pada objek game yang mendapatkan fokus ketika pointer pertama memasukinya dan pada yang kehilangan fokus ketika pointer terakhir meninggalkannya. | IMixedRealityFocusHandler |
Pointer Down / Dragged / Up / Clicked | Dinaikkan ke penunjuk laporan tekan, seret dan lepaskan. | IMixedRealityPointerHandler |
Sentuh Dimulai / Diperbarui / Selesai | Dibesarkan oleh penunjuk sadar sentuh suka PokePointer melaporkan aktivitas sentuh. |
IMixedRealityTouchHandler |
Catatan
IMixedRealityFocusChangedHandler
dan IMixedRealityFocusHandler
harus ditangani dalam objek tempat objek dinaikkan. Dimungkinkan untuk menerima peristiwa fokus secara global tetapi, tidak seperti peristiwa input lainnya, penanganan aktivitas global tidak akan memblokir penerimaan peristiwa berdasarkan fokus (peristiwa akan diterima oleh handler global dan objek yang sesuai dalam fokus).
Peristiwa input penunjuk sedang beraksi
Peristiwa input pointer dikenali dan ditangani oleh sistem input MRTK dengan cara yang sama seperti peristiwa input reguler. Perbedaannya adalah bahwa peristiwa input pointer hanya ditangani oleh GameObject dalam fokus oleh penunjuk yang menembakkan peristiwa input, serta penangan input global. Peristiwa input reguler ditangani oleh GameObjects sebagai fokus untuk semua pointer aktif.
- Sistem input MRTK mengenali peristiwa input telah terjadi
- Sistem input MRTK mengaktifkan fungsi antarmuka yang relevan untuk peristiwa input ke semua handler input global yang terdaftar
- Sistem input menentukan GameObject mana yang menjadi fokus untuk penunjuk yang menembakkan peristiwa
- Sistem input menggunakan Sistem Peristiwa Unity untuk mengaktifkan fungsi antarmuka yang relevan untuk semua komponen yang cocok pada GameObject yang berfokus
- Jika pada titik mana pun peristiwa input telah ditandai sebagai digunakan, proses akan berakhir dan tidak ada GameObjects lebih lanjut yang akan menerima panggilan balik.
- Contoh: Komponen yang mengimplementasikan antarmuka
IMixedRealityFocusHandler
akan dicari untuk keuntungan GameObject atau kehilangan fokus - Catatan: Unity Event System akan menggelembung untuk mencari Induk GameObject jika tidak ada komponen yang cocok dengan antarmuka yang diinginkan yang ditemukan pada GameObject saat ini..
- Contoh: Komponen yang mengimplementasikan antarmuka
- Jika tidak ada penangan input global yang terdaftar dan tidak ada GameObject yang ditemukan dengan komponen/antarmuka yang cocok, maka sistem input akan memanggil setiap penangan input terdaftar fallback
Contoh
Di bawah ini adalah contoh skrip yang mengubah warna perender terlampir saat pointer mengambil atau meninggalkan fokus atau saat penunjuk memilih objek.
public class ColorTap : MonoBehaviour, IMixedRealityFocusHandler, IMixedRealityPointerHandler
{
private Color color_IdleState = Color.cyan;
private Color color_OnHover = Color.white;
private Color color_OnSelect = Color.blue;
private Material material;
private void Awake()
{
material = GetComponent<Renderer>().material;
}
void IMixedRealityFocusHandler.OnFocusEnter(FocusEventData eventData)
{
material.color = color_OnHover;
}
void IMixedRealityFocusHandler.OnFocusExit(FocusEventData eventData)
{
material.color = color_IdleState;
}
void IMixedRealityPointerHandler.OnPointerDown(
MixedRealityPointerEventData eventData) { }
void IMixedRealityPointerHandler.OnPointerDragged(
MixedRealityPointerEventData eventData) { }
void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
material.color = color_OnSelect;
}
}
Penunjuk kueri
Dimungkinkan untuk mengumpulkan semua pointer yang saat ini aktif dengan mengulangi sumber input yang tersedia (yaitu pengontrol dan input yang tersedia) untuk menemukan pointer mana yang melekat padanya.
var pointers = new HashSet<IMixedRealityPointer>();
// Find all valid pointers
foreach (var inputSource in CoreServices.InputSystem.DetectedInputSources)
{
foreach (var pointer in inputSource.Pointers)
{
if (pointer.IsInteractionEnabled && !pointers.Contains(pointer))
{
pointers.Add(pointer);
}
}
}
Penunjuk utama
Pengembang dapat berlangganan peristiwa FocusProviders PrimaryPointerChanged untuk diberi tahu ketika penunjuk utama dalam fokus telah berubah. Ini bisa sangat berguna untuk mengidentifikasi apakah pengguna saat ini berinteraksi dengan adegan melalui tatapan atau sinar tangan atau sumber input lain.
private void OnEnable()
{
var focusProvider = CoreServices.InputSystem?.FocusProvider;
focusProvider?.SubscribeToPrimaryPointerChanged(OnPrimaryPointerChanged, true);
}
private void OnPrimaryPointerChanged(IMixedRealityPointer oldPointer, IMixedRealityPointer newPointer)
{
...
}
private void OnDisable()
{
var focusProvider = CoreServices.InputSystem?.FocusProvider;
focusProvider?.UnsubscribeFromPrimaryPointerChanged(OnPrimaryPointerChanged);
// This flushes out the current primary pointer
OnPrimaryPointerChanged(null, null);
}
Adegan PrimaryPointerExample
(Aset/MRTK/Contoh/Demo/Input/Adegan/PrimaryPointer) menunjukkan cara menggunakan PrimaryPointerChangedHandler
untuk peristiwa untuk merespons penunjuk utama baru.
Hasil pointer
Properti penunjuk Result
berisi hasil saat ini untuk kueri adegan yang digunakan untuk menentukan objek dengan fokus. Untuk pointer raycast, seperti yang dibuat secara default untuk pengontrol gerakan, input tatapan dan sinar tangan, itu akan berisi lokasi dan normal hit raycast.
private void IMixedRealityPointerHandler.OnPointerClicked(MixedRealityPointerEventData eventData)
{
var result = eventData.Pointer.Result;
var spawnPosition = result.Details.Point;
var spawnRotation = Quaternion.LookRotation(result.Details.Normal);
Instantiate(MyPrefab, spawnPosition, spawnRotation);
}
Adegan PointerResultExample
(Assets/MRTK/Examples/Demos/Input/Scenes/PointerResult/PointerResultExample.unity) menunjukkan cara menggunakan pointer Result
untuk menelurkan objek di lokasi hit.
Menonaktifkan penunjuk
Untuk mengaktifkan dan menonaktifkan penunjuk (misalnya, untuk menonaktifkan sinar tangan), atur PointerBehavior
untuk jenis pointer tertentu melalui PointerUtils
.
// Disable the hand rays
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff);
// Disable hand rays for the right hand only
PointerUtils.SetHandRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Right);
// Disable the gaze pointer
PointerUtils.SetGazePointerBehavior(PointerBehavior.AlwaysOff);
// Set the behavior to match HoloLens 1
// Note, if on HoloLens 2, you must configure your pointer profile to make the GGV pointer show up for articulated hands.
public void SetHoloLens1()
{
PointerUtils.SetPokePointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetGrabPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetRayPointerBehavior(PointerBehavior.AlwaysOff, Handedness.Any);
PointerUtils.SetGGVBehavior(PointerBehavior.Default);
}
Lihat PointerUtils
dan TurnPointersOnOff
untuk contoh selengkapnya.
Interaksi penunjuk melalui editor
Untuk peristiwa pointer yang ditangani oleh IMixedRealityPointerHandler
, MRTK memberikan kenyamanan lebih lanjut dalam bentuk PointerHandler
komponen, yang memungkinkan peristiwa pointer ditangani langsung melalui Unity Events.
Tingkat penunjuk
Pointer yang jauh memiliki pengaturan yang membatasi seberapa jauh mereka akan raycast dan berinteraksi dengan objek lain di adegan. Secara default, nilai ini diatur ke 10 meter. Nilai ini dipilih untuk tetap konsisten dengan perilaku shell HoloLens.
Ini dapat diubah dengan memperbarui DefaultControllerPointer
bidang komponen prefab ShellHandRayPointer
:
Pointer Extent - Ini mengontrol jarak maksimum yang akan berinteraksi dengan pointer.
Jangkauan Pointer Default - Ini mengontrol panjang sinar/garis penunjuk yang akan merender saat penunjuk tidak berinteraksi dengan apa pun.