MR Input 213: Pengontrol gerakan

Catatan

Tutorial akademi Mixed Reality dirancang dengan HoloLens (generasi ke-1) dan Mixed Reality Immersive Headsets dalam pikiran. Dengan demikian, kami merasa penting untuk meninggalkan tutorial ini di tempat bagi pengembang yang masih mencari panduan dalam mengembangkan untuk perangkat tersebut. Tutorial ini tidak akan diperbarui dengan toolset atau interaksi terbaru yang digunakan untuk HoloLens 2. Mereka akan dipertahankan untuk terus bekerja pada perangkat yang didukung. Serangkaian tutorial baru telah diposting untuk HoloLens 2.

Pengontrol gerakan di dunia realitas campuran menambahkan tingkat interaktivitas lain. Dengan pengontrol gerakan, kita dapat langsung berinteraksi dengan objek dengan cara yang lebih alami, mirip dengan interaksi fisik kita dalam kehidupan nyata, meningkatkan perendaman dan kesenangan dalam pengalaman aplikasi Anda.

Dalam MR Input 213, kita akan menjelajahi peristiwa input pengontrol gerakan dengan menciptakan pengalaman lukisan spasial sederhana. Dengan aplikasi ini, pengguna dapat melukis di ruang tiga dimensi dengan berbagai jenis kuas dan warna.

Topik yang tercakup dalam tutorial ini

MixedReality213 Topic1 MixedReality213 Topic2 MixedReality213 Topic3
Visualisasi pengontrol Peristiwa input pengontrol Pengontrol dan UI kustom
Pelajari cara merender model pengontrol gerakan dalam mode game dan runtime Unity. Pahami berbagai jenis peristiwa tombol dan aplikasinya. Pelajari cara melapisi elemen UI di atas pengontrol atau menyesuaikannya sepenuhnya.

Dukungan perangkat

Kursus HoloLens Headset imersif
MR Input 213: Pengontrol gerakan ✔️

Sebelum memulai

Prasyarat

Lihat daftar periksa penginstalan untuk headset imersif di halaman ini.

File proyek

Catatan

Jika Anda ingin melihat melalui kode sumber sebelum mengunduh, kode tersebut tersedia di GitHub.

Penyiapan Unity

Tujuan

  • Optimalkan Unity untuk pengembangan Windows Mixed Reality
  • Menyiapkan Kamera Mixed Reality
  • Lingkungan penyiapan

Petunjuk

  • Mulai Unity.

  • Pilih Buka.

  • Navigasikan ke Desktop Anda dan temukan folder MixedReality213-master yang sebelumnya Anda batalkan arsipnya.

  • Klik Pilih Folder.

  • Setelah Unity selesai memuat file proyek, Anda akan dapat melihat editor Unity.

  • Di Unity, pilih Pengaturan Build File>.

    MR213_BuildSettings

  • Pilih Platform Windows Universal di daftar Platform dan klik tombol Beralih Platform.

  • Atur Perangkat Target ke Perangkat apa pun

  • Atur Jenis Build ke D3D

  • Atur SDK ke Terinstal Terbaru

  • Periksa Proyek Unity C#

    • Ini memungkinkan Anda memodifikasi file skrip dalam proyek Visual Studio tanpa membangun kembali proyek Unity.
  • Klik Pengaturan Pemutar.

  • Di panel Inspektur , gulir ke bawah ke bawah

  • Di Pengaturan XR, periksa Realitas Virtual yang Didukung

  • Di bawah SDK Virtual Reality, pilih Windows Mixed Reality

    MR213_XRSettings

  • Tutup jendela Pengaturan Build .

Struktur proyek

Tutorial ini menggunakan Mixed Reality Toolkit - Unity. Anda dapat menemukan rilis di halaman ini.

ProjectStructure

Adegan yang diselesaikan untuk referensi Anda

  • Anda akan menemukan dua adegan Unity yang telah selesai di bawah folder Adegan .
    • MixedReality213: Adegan lengkap dengan sikat tunggal
    • MixedReality213Advanced: Adegan yang diselesaikan untuk desain tingkat lanjut dengan beberapa kuas

Penyiapan Adegan Baru untuk tutorial

  • Di Unity, klik File > Adegan Baru

  • Hapus Kamera Utama dan Lampu Arah

  • Dari panel Proyek, cari dan seret prefab berikut ke panel Hierarki :

    • Aset/HoloToolkit/Input/Prefabs/MixedRealityCamera
    • Aset/AppPrefabs/Lingkungan

    Kamera dan Lingkungan

  • Ada dua prefab kamera di Mixed Reality Toolkit:

    • MixedRealityCamera.prefab: Hanya kamera
    • MixedRealityCameraParent.prefab: Kamera + Teleportasi + Batas
    • Dalam tutorial ini, kita akan menggunakan MixedRealityCamera tanpa fitur teleportasi. Karena itu, kami menambahkan prefab Lingkungan sederhana yang berisi lantai dasar untuk membuat pengguna merasa membumi.
    • Untuk mempelajari selengkapnya tentang teleportasi dengan MixedRealityCameraParent, lihat Desain tingkat lanjut - Teleportasi dan locomotion

Penyiapan Skybox

  • Klik Pengaturan Pencahayaan > Jendela >

  • Klik lingkaran di sisi kanan bidang Material Skybox

  • Ketik 'abu-abu' dan pilih SkyboxGray (Aset/AppPrefabs/Support/Materials/SkyboxGray.mat)

    Mengatur skybox

  • Centang opsi Skybox untuk dapat melihat skybox gradien abu-abu yang ditetapkan

    Opsi alihkan skybox

  • Adegan dengan MixedRealityCamera, Environment dan skybox abu-abu akan terlihat seperti ini.

    Lingkungan MixedReality213

  • Klik Adegan Penyimpanan File > sebagai

  • Simpan adegan Anda di bawah folder Adegan dengan nama apa pun

Bab 1 - Visualisasi pengontrol

Tujuan

  • Pelajari cara merender model pengontrol gerakan dalam mode permainan Unity dan pada runtime.

Windows Mixed Reality menyediakan model pengontrol animasi untuk visualisasi pengontrol. Ada beberapa pendekatan yang dapat Anda ambil untuk visualisasi pengontrol di aplikasi Anda:

  • Default - Menggunakan pengontrol default tanpa modifikasi
  • Hibrid - Menggunakan pengontrol default, tetapi menyesuaikan beberapa elemennya atau melapisi komponen UI
  • Penggantian - Menggunakan model 3D anda sendiri yang disesuaikan untuk pengontrol

Dalam bab ini, kita akan mempelajari tentang contoh penyesuaian pengontrol ini.

Petunjuk

  • Di panel Proyek , ketik MotionControllers di kotak pencarian . Anda juga dapat menemukannya di bawah Aset/HoloToolkit/Input/Prefabs/.
  • Seret prefab MotionControllers ke panel Hierarki .
  • Klik prefab MotionControllers di panel Hierarki .

Prefab MotionControllers

Prefab MotionControllers memiliki skrip MotionControllerVisualizer yang menyediakan slot untuk model pengontrol alternatif. Jika Anda menetapkan model 3D kustom Anda sendiri seperti tangan atau pedang dan memeriksa 'Selalu Gunakan Model Kiri/Kanan Alternatif', Anda akan melihatnya alih-alih model default. Kami akan menggunakan slot ini di Bab 4 untuk mengganti model pengontrol dengan kuas.

MR213_ControllerVisualizer

Petunjuk

  • Di panel Inspektur , klik dua kali skrip MotionControllerVisualizer untuk melihat kode di Visual Studio

Skrip MotionControllerVisualizer

Kelas MotionControllerVisualizer dan MotionControllerInfo menyediakan sarana untuk mengakses & memodifikasi model pengontrol default. MotionControllerVisualizer berlangganan peristiwa InteractionSourceDetected Unity dan secara otomatis membuat instans model pengontrol saat ditemukan.

protected override void Awake()
{
    ...
    InteractionManager.InteractionSourceDetected += InteractionManager_InteractionSourceDetected;
    InteractionManager.InteractionSourceLost += InteractionManager_InteractionSourceLost;
    ...
}

Model pengontrol dikirimkan sesuai dengan spesifikasi glTF. Format ini telah dibuat untuk menyediakan format umum, sekaligus meningkatkan proses di balik pengiriman dan pembukaan kemasan aset 3D. Dalam hal ini, kita perlu mengambil dan memuat model pengontrol pada runtime, karena kita ingin membuat pengalaman pengguna semulus mungkin, dan tidak dijamin versi pengontrol gerakan mana yang mungkin digunakan pengguna. Kursus ini, melalui Mixed Reality Toolkit, menggunakan versi proyek UnityGLTF Khronos Group.

Setelah pengontrol dikirimkan, skrip dapat menggunakan MotionControllerInfo untuk menemukan transformasi untuk elemen pengontrol tertentu sehingga dapat memposisikan diri dengan benar.

Di bab selanjutnya, kita akan mempelajari cara menggunakan skrip ini untuk melampirkan elemen UI ke pengontrol.

Dalam beberapa skrip, Anda akan menemukan blok kode dengan #if! UNITY_EDITOR atau UNITY_WSA. Blok kode ini hanya berjalan pada runtime UWP saat Anda menyebarkan ke Windows. Ini karena set API yang digunakan oleh editor Unity dan runtime aplikasi UWP berbeda.

  • Simpan adegan dan klik tombol putar .

Anda akan dapat melihat adegan dengan pengontrol gerakan di headset Anda. Anda dapat melihat animasi terperinci untuk klik tombol, gerakan thumbstick, dan penyorotan sentuhan touchpad.

MR213_Controller Visualisasi Default

Bab 2 - Melampirkan elemen UI ke pengontrol

Tujuan

  • Pelajari tentang elemen pengontrol gerakan
  • Pelajari cara melampirkan objek ke bagian tertentu dari pengontrol

Dalam bab ini, Anda akan mempelajari cara menambahkan elemen antarmuka pengguna ke pengontrol yang dapat diakses dan dimanipulasi pengguna kapan saja dengan mudah. Anda juga akan mempelajari cara menambahkan UI pemilih warna sederhana menggunakan input touchpad.

Petunjuk

  • Di panel Proyek , cari skrip MotionControllerInfo .
  • Dari hasil pencarian, klik dua kali skrip MotionControllerInfo untuk melihat kode di Visual Studio.

Skrip MotionControllerInfo

Langkah pertama adalah memilih elemen pengontrol mana yang ingin Anda lampirkan UI. Elemen-elemen ini didefinisikan dalam ControllerElementEnum di MotionControllerInfo.cs.

MR213 MotionControllerElements

  • Rumah
  • Menu
  • Memahami
  • Thumbstick
  • Pilih
  • Touchpad
  • Pose penunjuk - elemen ini mewakili ujung pengontrol yang menunjuk ke depan arah.

Petunjuk

  • Di panel Proyek , cari skrip AttachToController .
  • Dari hasil pencarian, klik dua kali skrip AttachToController untuk melihat kode di Visual Studio.

Skrip AttachToController

Skrip AttachToController menyediakan cara sederhana untuk melampirkan objek apa pun ke handedness dan elemen pengontrol tertentu.

Di AttachElementToController(),

  • Periksa handedness menggunakan MotionControllerInfo.Handedness
  • Dapatkan elemen tertentu dari pengontrol menggunakan MotionControllerInfo.TryGetElement()
  • Setelah mengambil transformasi elemen dari model pengontrol, induk objek di bawahnya dan atur posisi lokal objek & rotasi ke nol.
public MotionControllerInfo.ControllerElementEnum Element { get { return element; } }

private void AttachElementToController(MotionControllerInfo newController)
{
     if (!IsAttached && newController.Handedness == handedness)
     {
          if (!newController.TryGetElement(element, out elementTransform))
          {
               Debug.LogError("Unable to find element of type " + element + " under controller " + newController.ControllerParent.name + "; not attaching.");
               return;
          }

          controller = newController;

          SetChildrenActive(true);

          // Parent ourselves under the element and set our offsets
          transform.parent = elementTransform;
          transform.localPosition = positionOffset;
          transform.localEulerAngles = rotationOffset;
          if (setScaleOnAttach)
          {
               transform.localScale = scale;
          }

          // Announce that we're attached
          OnAttachToController();
          IsAttached = true;
     }
}

Cara paling sederhana untuk menggunakan skrip AttachToController adalah dengan mewarisinya, seperti yang telah kita lakukan dalam kasus ColorPickerWheel. Cukup ganti fungsi OnAttachToController dan OnDetachFromController untuk melakukan penyiapan/perincian Anda saat pengontrol terdeteksi/terputus.

Petunjuk

  • Di panel Proyek , ketik di kotak pencarian ColorPickerWheel. Anda juga dapat menemukannya di bawah Aset/AppPrefabs/.
  • Seret prefab ColorPickerWheel ke panel Hierarki .
  • Klik prefab ColorPickerWheel di panel Hierarki .
  • Di panel Pemeriksa , klik dua kali Skrip ColorPickerWheel untuk melihat kode di Visual Studio.

Prefab ColorPickerWheel

Skrip ColorPickerWheel

Karena ColorPickerWheel mewarisi AttachToController, itu menunjukkan Handedness dan Element di panel Inspektur . Kami akan melampirkan UI ke elemen Touchpad di pengontrol kiri.

Skrip ColorPickerWheel

ColorPickerWheel mengambil alih OnAttachToController dan OnDetachFromController untuk berlangganan peristiwa input yang akan digunakan di bab berikutnya untuk pemilihan warna dengan input touchpad.

public class ColorPickerWheel : AttachToController, IPointerTarget
{
    protected override void OnAttachToController()
    {
        // Subscribe to input now that we're parented under the controller
        InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
    }

    protected override void OnDetachFromController()
    {
        Visible = false;

        // Unsubscribe from input now that we've detached from the controller
        InteractionManager.InteractionSourceUpdated -= InteractionSourceUpdated;
    }
    ...
}
  • Simpan adegan dan klik tombol putar .

Metode alternatif untuk melampirkan objek ke pengontrol

Kami menyarankan agar skrip Anda mewarisi dari AttachToController dan menimpa OnAttachToController. Namun, ini mungkin tidak selalu mungkin. Alternatifnya adalah menggunakannya sebagai komponen mandiri. Ini dapat berguna ketika Anda ingin melampirkan prefab yang ada ke pengontrol tanpa merefaktor skrip Anda. Cukup minta kelas Anda menunggu IsAttached diatur ke true sebelum melakukan pengaturan apa pun. Cara paling sederhana untuk melakukan ini adalah dengan menggunakan coroutine untuk 'Start.'

private IEnumerator Start() {
    AttachToController attach = gameObject.GetComponent<AttachToController>();

    while (!attach.IsAttached) {
        yield return null;
    }

    // Perform setup here
}

Bab 3 - Bekerja dengan input touchpad

Tujuan

  • Pelajari cara mendapatkan peristiwa data input touchpad
  • Pelajari cara menggunakan informasi posisi sumbu touchpad untuk pengalaman aplikasi Anda

Petunjuk

  • Di panel Hierarki , klik ColorPickerWheel
  • Di panel Inspektur , di bawah Animator, klik dua kali ColorPickerWheelController
  • Anda akan dapat melihat tab Animator dibuka

Memperlihatkan/menyembunyikan UI dengan pengontrol Animasi Unity

Untuk menampilkan dan menyembunyikan UI ColorPickerWheel dengan animasi, kami menggunakan sistem animasi Unity. Mengatur properti ColorPickerWheelterlihat ke pemicu true atau false Tampilkan dan Sembunyikan pemicu animasi. Tampilkan dan Sembunyikan parameter didefinisikan dalam pengontrol animasi ColorPickerWheelController .

Pengontrol Animasi Unity

Petunjuk

  • Di panel Hierarki , pilih ColorPickerWheel prefab
  • Di panel Inspektur , klik dua kali skrip ColorPickerWheel untuk melihat kode di Visual Studio

Skrip ColorPickerWheel

ColorPickerWheel berlangganan acara Unity's InteractionSourceUpdated untuk mendengarkan peristiwa touchpad.

Di InteractionSourceUpdated(), skrip terlebih dahulu memeriksa untuk memastikan bahwa skrip:

  • sebenarnya adalah peristiwa touchpad (obj.state.touchpadTouched)
  • berasal dari pengontrol kiri (obj.state.source.keserangan)

Jika keduanya benar, posisi touchpad (obj.state.touchpadPosition) ditetapkan ke selectorPosition.

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness && obj.state.touchpadTouched)
    {
        Visible = true;
        selectorPosition = obj.state.touchpadPosition;
    }
}

Di Update(), berdasarkan properti yang terlihat , ini memicu pemicu Tampilkan dan Sembunyikan animasi di komponen animator pemilih warna

if (visible != visibleLastFrame)
{
    if (visible)
    {
        animator.SetTrigger("Show");
    }
    else
    {
        animator.SetTrigger("Hide");
    }
}

Di Update(), selectorPosition digunakan untuk mentransmisikan sinar pada collider jala roda warna, yang mengembalikan posisi UV. Posisi ini kemudian dapat digunakan untuk menemukan koordinat piksel dan nilai warna tekstur roda warna. Nilai ini dapat diakses oleh skrip lain melalui properti SelectedColor .

Raycasting Roda Pemilih Warna

...
    // Clamp selector position to a radius of 1
    Vector3 localPosition = new Vector3(selectorPosition.x * inputScale, 0.15f, selectorPosition.y * inputScale);
    if (localPosition.magnitude > 1)
    {
        localPosition = localPosition.normalized;
    }
    selectorTransform.localPosition = localPosition;

    // Raycast the wheel mesh and get its UV coordinates
    Vector3 raycastStart = selectorTransform.position + selectorTransform.up * 0.15f;
    RaycastHit hit;
    Debug.DrawLine(raycastStart, raycastStart - (selectorTransform.up * 0.25f));

    if (Physics.Raycast(raycastStart, -selectorTransform.up, out hit, 0.25f, 1 << colorWheelObject.layer, QueryTriggerInteraction.Ignore))
    {
        // Get pixel from the color wheel texture using UV coordinates
        Vector2 uv = hit.textureCoord;
        int pixelX = Mathf.FloorToInt(colorWheelTexture.width * uv.x);
        int pixelY = Mathf.FloorToInt(colorWheelTexture.height * uv.y);
        selectedColor = colorWheelTexture.GetPixel(pixelX, pixelY);
        selectedColor.a = 1f;
    }
    // Set the selector's color and blend it with white to make it visible on top of the wheel
    selectorRenderer.material.color = Color.Lerp (selectedColor, Color.white, 0.5f);
}

Bab 4 - Mengambil alih model pengontrol

Tujuan

  • Pelajari cara mengganti model pengontrol dengan model 3D kustom.

MR213_BrushToolOverride

Petunjuk

  • Klik MotionControllers di panel Hierarki .
  • Klik lingkaran di sisi kanan bidang Pengontrol Kanan Alternatif .
  • Ketik 'BrushController' dan pilih prefab dari hasilnya. Anda dapat menemukannya di bawah Aset/AppPrefabs/BrushController.
  • Centang Selalu Gunakan Model Kanan Alternatif

MR213_BrushToolOverrideSlot

Prefab BrushController tidak harus disertakan dalam panel Hierarki . Namun, untuk memeriksa komponen anaknya:

  • Di panel Proyek , ketik BrushController dan seret prefab BrushController ke panel Hierarki .

MR213_BrushTool_Prefab2

Anda akan menemukan komponen Tip di BrushController. Kami akan menggunakan transformasinya untuk memulai/menghentikan garis gambar.

  • Hapus BrushController dari panel Hierarki .
  • Simpan adegan dan klik tombol putar . Anda akan dapat melihat model kuas menggantikan pengontrol gerakan tangan kanan.

Bab 5 - Melukis dengan Input pilih

Tujuan

  • Pelajari cara menggunakan peristiwa tombol Pilih untuk memulai dan menghentikan gambar garis

Petunjuk

  • Cari prefab BrushController di panel Proyek .
  • Di panel Inspektur , klik dua kali Skrip BrushController untuk melihat kode di Visual Studio

Skrip BrushController

BrushController berlangganan peristiwa InteractionManager's InteractionSourcePressed dan InteractionSourceReleased . Ketika peristiwa InteractionSourcePressed dipicu , properti Draw kuas diatur ke true; ketika peristiwa InteractionSourceReleased dipicu, properti Draw kuas diatur ke false.

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = true;
    }
}

private void InteractionSourceReleased(InteractionSourceReleasedEventArgs obj)
{
    if (obj.state.source.handedness == InteractionSourceHandedness.Right && obj.pressType == InteractionSourcePressType.Select)
    {
        Draw = false;
    }
}

Sementara Draw diatur ke true, kuas akan menghasilkan poin dalam Unity LineRenderer yang dibuat. Referensi ke prefab ini disimpan di bidang Stroke Prefab kuas.

private IEnumerator DrawOverTime()
{
    // Get the position of the tip
    Vector3 lastPointPosition = tip.position;

    ...

    // Create a new brush stroke
    GameObject newStroke = Instantiate(strokePrefab);
    LineRenderer line = newStroke.GetComponent<LineRenderer>();
    newStroke.transform.position = startPosition;
    line.SetPosition(0, tip.position);
    float initialWidth = line.widthMultiplier;

    // Generate points in an instantiated Unity LineRenderer
    while (draw)
    {
        // Move the last point to the draw point position
        line.SetPosition(line.positionCount - 1, tip.position);
        line.material.color = colorPicker.SelectedColor;
        brushRenderer.material.color = colorPicker.SelectedColor;
        lastPointAddedTime = Time.unscaledTime;
        // Adjust the width between 1x and 2x width based on strength of trigger pull
        line.widthMultiplier = Mathf.Lerp(initialWidth, initialWidth * 2, width);

        if (Vector3.Distance(lastPointPosition, tip.position) > minPositionDelta || Time.unscaledTime > lastPointAddedTime + maxTimeDelta)
        {
            // Spawn a new point
            lastPointAddedTime = Time.unscaledTime;
            lastPointPosition = tip.position;
            line.positionCount += 1;
            line.SetPosition(line.positionCount - 1, lastPointPosition);
        }
        yield return null;
    }
}

Untuk menggunakan warna yang saat ini dipilih dari UI roda pemilih warna, BrushController harus memiliki referensi ke objek ColorPickerWheel . Karena prefab BrushController dibuat saat runtime sebagai pengontrol pengganti, referensi apa pun ke objek dalam adegan harus diatur pada runtime. Dalam hal ini kami menggunakan GameObject.FindObjectOfType untuk menemukan ColorPickerWheel:

private void OnEnable()
{
    // Locate the ColorPickerWheel
    colorPicker = FindObjectOfType<ColorPickerWheel>();

    // Assign currently selected color to the brush’s material color
    brushRenderer.material.color = colorPicker.SelectedColor;
    ...
}
  • Simpan adegan dan klik tombol putar . Anda akan dapat menggambar garis dan melukis menggunakan tombol pilih pada pengontrol kanan.

Bab 6 - Pemijahan objek dengan Pilih input

Tujuan

  • Pelajari cara menggunakan peristiwa input tombol Pilih dan Pahami
  • Pelajari cara membuat instans objek

Petunjuk

  • Di panel Proyek , ketik ObjectSpawner di kotak pencarian. Anda juga dapat menemukannya di bawah Aset/AppPrefabs/

  • Seret prefab ObjectSpawner ke panel Hierarki .

  • Klik ObjectSpawner di panel Hierarki .

  • ObjectSpawner memiliki bidang bernama Sumber Warna.

  • Dari panel Hierarki , seret referensi ColorPickerWheel ke bidang ini.

    Pemeriksa Spawner Objek

  • Klik prefab ObjectSpawner di panel Hierarki .

  • Di panel Inspektur , klik dua kali ObjectSpawner Script untuk melihat kode di Visual Studio.

Skrip ObjectSpawner

ObjectSpawner membuat instans salinan jala primitif (kubus, bola, silinder) ke dalam ruang. Ketika InteractionSourcePressed terdeteksi , ia memeriksa keserangan dan apakah itu peristiwa InteractionSourcePressType.Grasp atau InteractionSourcePressType.Select .

Untuk peristiwa Grasp , ini menaikkan indeks jenis jala saat ini (bola, kubus, silinder)

private void InteractionSourcePressed(InteractionSourcePressedEventArgs obj)
{
    // Check handedness, see if it is left controller
    if (obj.state.source.handedness == handedness)
    {
        switch (obj.pressType)
        {
            // If it is Select button event, spawn object
            case InteractionSourcePressType.Select:
                if (state == StateEnum.Idle)
                {
                    // We've pressed the grasp - enter spawning state
                    state = StateEnum.Spawning;
                    SpawnObject();
                }
                break;

            // If it is Grasp button event
            case InteractionSourcePressType.Grasp:

                // Increment the index of current mesh type (sphere, cube, cylinder)
                meshIndex++;
                if (meshIndex >= NumAvailableMeshes)
                {
                    meshIndex = 0;
                }
                break;

            default:
                break;
        }
    }
}

Untuk peristiwa Pilih , di SpawnObject(), objek baru dibuat, tidak diindukkan, dan dirilis ke dunia.

private void SpawnObject()
{
    // Instantiate the spawned object
    GameObject newObject = Instantiate(displayObject.gameObject, spawnParent);
    // Detach the newly spawned object
    newObject.transform.parent = null;
    // Reset the scale transform to 1
    scaleParent.localScale = Vector3.one;
    // Set its material color so its material gets instantiated
    newObject.GetComponent<Renderer>().material.color = colorSource.SelectedColor;
}

ObjectSpawner menggunakan ColorPickerWheel untuk mengatur warna bahan objek tampilan. Objek yang ditelurkan diberikan instans bahan ini sehingga mereka akan mempertahankan warnanya.

  • Simpan adegan dan klik tombol putar .

Anda akan dapat mengubah objek dengan tombol Grasp dan menelurkan objek dengan tombol Pilih.

Membuat dan menyebarkan aplikasi ke Portal Mixed Reality

  • Di Unity, pilih Pengaturan Build File>.
  • Klik Tambahkan Adegan Terbuka untuk menambahkan adegan saat ini ke Adegan Dalam Build.
  • Klik Bangun.
  • Buat Folder Baru bernama "Aplikasi".
  • Klik tunggal folder Aplikasi .
  • Klik Pilih Folder.
  • Ketika Unity selesai, jendela File Explorer akan muncul.
  • Buka folder Aplikasi .
  • Klik dua kali file Solusi Visual Studio YourSceneName.sln .
  • Menggunakan toolbar atas di Visual Studio, ubah target dari Debug ke Rilis dan dari ARM ke X64.
  • Klik panah drop-down di samping tombol Perangkat, dan pilih Komputer Lokal.
  • Klik Debug -> Mulai Tanpa penelusuran kesalahan di menu atau tekan Ctrl + F5.

Sekarang aplikasi dibuat dan diinstal di portal Mixed Reality. Anda dapat meluncurkannya lagi melalui menu Mulai di portal Mixed Reality.

Desain tingkat lanjut - Alat kuas dengan tata letak radial

MixedReality213 Main

Dalam bab ini, Anda akan mempelajari cara mengganti model pengontrol gerakan default dengan koleksi alat kuas kustom. Untuk referensi Anda, Anda dapat menemukan adegan lengkap MixedReality213Advanced di bawah folder Adegan .

Petunjuk

  • Di panel Proyek , ketik BrushSelector di kotak pencarian . Anda juga dapat menemukannya di bawah Aset/AppPrefabs/

  • Seret prefab BrushSelector ke panel Hierarki .

  • Untuk organisasi, buat GameObject kosong yang disebut Brush

  • Seret prefab berikut dari panel Proyek ke Dalam Kuas

    • Aset/AppPrefabs/BrushFat
    • Aset/AppPrefabs/BrushThin
    • Aset/AppPrefabs/Penghapus
    • Aset/AppPrefabs/MarkerFat
    • Aset/AppPrefabs/MarkerThin
    • Aset/AppPrefabs/Pensil

    Kuas

  • Klik prefab MotionControllers di panel Hierarki .

  • Di panel Inspektur , hapus centang Selalu Gunakan Model Kanan Alternatif pada Visualizer Pengontrol Gerakan

  • Di panel Hierarki , klik BrushSelector

  • BrushSelector memiliki bidang bernama ColorPicker

  • Dari panel Hierarki , seret ColorPickerWheel ke bidang ColorPicker di panel Pemeriksa .

    Menetapkan ColorPickerWheel ke Pemilih Kuas

  • Di panel Hierarki , di bawah prefab BrushSelector , pilih objek Menu .

  • Di panel Pemeriksa , di bawah komponen LineObjectCollection , buka menu dropdown Array objek . Anda akan melihat 6 slot kosong.

  • Dari panel Hierarki , seret setiap prefab yang diinduk di bawah Brush GameObject ke slot ini dalam urutan apa pun. (Pastikan Anda menyeret prefab dari adegan, bukan prefab di folder proyek.)

Pemilih Kuas

Prefab BrushSelector

Karena BrushSelector mewarisi AttachToController, ini menunjukkan opsi Handedness dan Element di panel Inspektur . Kami memilih Pose Kanan dan Menunjuk untuk melampirkan alat kuas ke pengontrol tangan kanan dengan arah ke depan.

BrushSelector menggunakan dua utilitas:

  • Elips: digunakan untuk menghasilkan titik dalam spasi di sepanjang bentuk elips.
  • LineObjectCollection: mendistribusikan objek menggunakan titik yang dihasilkan oleh kelas Baris apa pun (misalnya, Elips). Inilah yang akan kita gunakan untuk menempatkan kuas kita di sepanjang bentuk Elips.

Jika digabungkan, utilitas ini dapat digunakan untuk membuat menu radial.

Skrip LineObjectCollection

LineObjectCollection memiliki kontrol untuk ukuran, posisi, dan rotasi objek yang didistribusikan di sepanjang garisnya. Ini berguna untuk membuat menu radial seperti pemilih kuas. Untuk membuat tampilan kuas yang menskalakan dari tidak ada saat mendekati posisi yang dipilih pusat, kurva ObjectScale memuncak di tengah dan meruncing di tepi.

Skrip BrushSelector

Dalam kasus BrushSelector, kami telah memilih untuk menggunakan animasi prosedural. Pertama, model kuas didistribusikan dalam elips oleh skrip LineObjectCollection . Kemudian, setiap kuas bertanggung jawab untuk mempertahankan posisinya di tangan pengguna berdasarkan nilai DisplayMode-nya , yang berubah berdasarkan pilihan. Kami memilih pendekatan prosedural karena kemungkinan besar transisi posisi sikat terganggu saat pengguna memilih kuas. Animasi Mecanim dapat menangani gangguan dengan anggun, tetapi cenderung lebih rumit daripada operasi Lerp sederhana.

BrushSelector menggunakan kombinasi keduanya. Ketika input touchpad terdeteksi, opsi kuas menjadi terlihat dan ditingkatkan di sepanjang menu radial. Setelah periode waktu habis (yang menunjukkan bahwa pengguna telah membuat pilihan) opsi kuas menurunkan skala lagi, hanya menyisakan kuas yang dipilih.

Memvisualisasikan input touchpad

Bahkan dalam kasus di mana model pengontrol telah diganti sepenuhnya, akan sangat membantu untuk menunjukkan input pada input model asli. Ini membantu membumikan tindakan pengguna pada kenyataannya. Untuk BrushSelector , kami telah memilih untuk membuat touchpad terlihat sebentar ketika input diterima. Ini dilakukan dengan mengambil elemen Touchpad dari pengontrol, mengganti bahannya dengan bahan kustom, lalu menerapkan gradien ke warna bahan tersebut berdasarkan terakhir kali input touchpad diterima.

protected override void OnAttachToController()
{
    // Turn off the default controller's renderers
    controller.SetRenderersVisible(false);

    // Get the touchpad and assign our custom material to it
    Transform touchpad;
    if (controller.TryGetElement(MotionControllerInfo.ControllerElementEnum.Touchpad, out touchpad))
    {
        touchpadRenderer = touchpad.GetComponentInChildren<MeshRenderer>();
        originalTouchpadMaterial = touchpadRenderer.material;
        touchpadRenderer.material = touchpadMaterial;
        touchpadRenderer.enabled = true;
    }

    // Subscribe to input now that we're parented under the controller
    InteractionManager.InteractionSourceUpdated += InteractionSourceUpdated;
}

private void Update()
{
    ...
    // Update our touchpad material
    Color glowColor = touchpadColor.Evaluate((Time.unscaledTime - touchpadTouchTime) / touchpadGlowLossTime);
    touchpadMaterial.SetColor("_EmissionColor", glowColor);
    touchpadMaterial.SetColor("_Color", glowColor);
    ...
}

Pemilihan alat kuas dengan input touchpad

Ketika pemilih kuas mendeteksi input touchpad yang ditekan, pemilih akan memeriksa posisi input untuk menentukan apakah input berada di kiri atau kanan.

Ketebalan stroke dengan selectPressedAmount

Alih-alih peristiwa InteractionSourcePressType.Select di InteractionSourcePressed(), Anda bisa mendapatkan nilai analog dari jumlah yang ditekan melalui selectPressedAmount. Nilai ini dapat diambil di InteractionSourceUpdated().

private void InteractionSourceUpdated(InteractionSourceUpdatedEventArgs obj)
{
    if (obj.state.source.handedness == handedness)
    {
        if (obj.state.touchpadPressed)
        {
            // Check which side we clicked
            if (obj.state.touchpadPosition.x < 0)
            {
                currentAction = SwipeEnum.Left;
            }
            else
            {
                currentAction = SwipeEnum.Right;
            }

            // Ping the touchpad material so it gets bright
            touchpadTouchTime = Time.unscaledTime;
        }

        if (activeBrush != null)
        {
            // If the pressed amount is greater than our threshold, draw
            if (obj.state.selectPressedAmount >= selectPressedDrawThreshold)
            {
                activeBrush.Draw = true;
                activeBrush.Width = ProcessSelectPressedAmount(obj.state.selectPressedAmount);
            }
            else
            {
                // Otherwise, stop drawing
                activeBrush.Draw = false;
                selectPressedSmooth = 0f;
            }
        }
    }
}

Skrip penghapus

Eraser adalah jenis kuas khusus yang menggantikan fungsi DrawOverTime()dasar Brush. Meskipun Draw benar, penghapus memeriksa untuk melihat apakah ujungnya bersinggungan dengan goresan kuas yang ada. Jika ya, mereka ditambahkan ke antrean untuk disusutkan dan dihapus.

Desain tingkat lanjut - Teleportasi dan locomotion

Jika Anda ingin mengizinkan pengguna untuk bergerak di sekitar adegan dengan teleportasi menggunakan thumbstick, gunakan MixedRealityCameraParent alih-alih MixedRealityCamera. Anda juga perlu menambahkan InputManager dan DefaultCursor. Karena MixedRealityCameraParent sudah menyertakan MotionControllers dan Boundary sebagai komponen turunan, Anda harus menghapus prefab MotionControllers dan Environment yang ada.

Petunjuk

  • Di panel Hierarki , hapus MixedRealityCamera, Environment dan MotionControllers

  • Dari panel Proyek, cari dan seret prefab berikut ke panel Hierarki :

    • Aset/AppPrefabs/Input/Prefabs/MixedRealityCameraParent
    • Aset/AppPrefabs/Input/Prefabs/InputManager
    • Aset/AppPrefabs/Input/Prefabs/Kursor/DefaultCursor

    Induk Kamera Mixed Reality

  • Di panel Hierarki , klik Manajer Input

  • Di panel Inspektur, gulir ke bawah ke bagian Pemilih Penunjuk Tunggal Sederhana

  • Dari panel Hierarki, seret DefaultCursor ke bidang Kursor

    Menetapkan DefaultCursor

  • Simpan adegan dan klik tombol putar . Anda akan dapat menggunakan thumbstick untuk memutar kiri/kanan atau teleport.

Akhir

Dan itulah akhir tutorial ini! Anda belajar:

  • Cara bekerja dengan model pengontrol gerakan dalam mode game dan runtime Unity.
  • Cara menggunakan berbagai jenis peristiwa tombol dan aplikasinya.
  • Cara melapisi elemen UI di atas pengontrol atau menyesuaikannya sepenuhnya.

Anda sekarang siap untuk mulai menciptakan pengalaman imersif Anda sendiri dengan pengontrol gerakan!

Adegan yang telah selesai

  • Di panel Proyek Unity klik folder Adegan .
  • Anda akan menemukan dua adegan Unity MixedReality213 dan MixedReality213Advanced.
    • MixedReality213: Adegan lengkap dengan sikat tunggal
    • MixedReality213Advanced: Menyelesaikan adegan dengan beberapa kuas dengan contoh jumlah tekan tombol pilih

Lihat juga