Game DevelopmentUnity 3DVirtual Reality

การเขียนเกม VR ด้วย SteamVR บน Unity ร่วมกับ HTC Vive

บทเรียนนี้เป็นการพัฒนาเกมรูปแบบ VR บน Unity 3D ร่วมกับ SteamVR ทดสอบผ่านอุปกรณ์ VR Headset ยอดนิยมอย่าง HTC Vive, ได้รับการสนับสนุนจากวิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี

สำหรับผมช่วงนี้เป็น หัวหน้าหลักสูตรการออกแบบเชิงโต้ตอบและการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ก็ได้มีโครงงานสร้างเกม VR สำหรับไปโชว์ในงาน GSL 2017 โดยให้นักศึกษาในสาขามาช่วยเหลืออยู่พักหนึ่ง ทำให้ไม่ค่อยได้รีวิวอะไรบนเว็บอยู่พักใหญ่ พอตอนนี้งานก็เป็นที่เรียบร้อยก็เลยมีโอกาสมารีวิวอุปกรณ์ HTC Vive ซึ่งเป็น Headset ยอดนิยมมาพัฒนาเกม VR บนโปรแกรม Unity3D เสียหน่อย ดังนั้นในบทความนี้จะประกอบไปด้วย โปรแกรมต่อไปนี้ครับ

  • ติดตั้ง Steam, SteamVR
  • โปรแกรม Unity3D
  • ติดตั้ง Driver ของ HTC Vive และจัดการ Room Setup ให้เรียบร้อย (ซึ่งใครที่ซื้ออุปกรณ์นี้มาคงทำเป็น)

บทความนี้ได้มาจากหลายๆ แหล่งเรียนรู้ทั้ง เว็บไซต์ http://www.leadingones.com, https://www.raywenderlich.com ทางผมก็ขออนุญาติมาย่อยให้ครับ

เริ่มต้นพัฒนาคือเปิด Unity ขึ้นมาครับเข้าไปที่ Asset Store ไปดาวน์โหลด และ import เจ้า Assets ที่ชื่อว่า Steam VR ครับ

ดาวน์โหลดเสร็จเรียบร้อยอย่าลืม Import เข้าไปใน Project ของเราครับ

หากทำการ Import เป็นที่เรียบร้อยแล้วพบหน้าจอนี้ก็ไม่ต้องสนใจอะไรครับ เป็นการตรวจสอบเวอร์ชัน ปกติธรรมดาก็กดตามนี้ครับ “Accept All”

คราวนี้เราจะได้ Folder ของตัว SteamVR เข้ามาเป็นส่วนหนึ่งของ Project ทำการเชื่อมต่อ อุปกรณ์เปิดโปรแกรม SteamVR ให้เรียบร้อยหลังจากนั้นไปดูที่ Folder ชื่อว่า “Prefabs” ใน SteamVR ครับ เราจะพบกับ “[CameraRig]” และ “[SteamVR]” ลากทั้งสองตัวไปวางที่ Hierarchy เลยครับ เราจะได้พื้นที่สำหรับเล่นเป็นตารางสีฟ้าอ่อน (เปลี่ยนสีได้)

อันที่จริงแค่นี้ก็เล่นได้แล้วครับ กด Play ไปเลยก็จะเดินไปมาในฉาก เห็น JoyController ของเราที่ถืออยู่ แทนมือของเราครับ สามารถเดินไปมาได้ในฉากโดยอ้างจากระบบ Sensor ของตัว BaseStation ทั้งสองฝั่งครับ ขอแค่มีพื้นที่กว้างๆ หน่อยเล็กน้อย

เราสามารถกางเจ้า CameraRig บน Hierarchy ได้จะพบกับ Controller (left) แทนมือซ้าย, Controller (right) แทนมือขวา และ Camera (head) แทนศรีษะของเราซึ่งเราสามารถปรับแต่งได้ดังนี้

ใน Controller (left) และ Controller (right) เราสามารถเขียนคำสั่ง SteamVR SDK เข้าไปตรวจสอบการกดปุ่ม Trigger ได้ ให้ลองสร้าง C# ขึ้นมาว่า TrackedController

using UnityEngine;

public class TrackedController: MonoBehaviour
{
  private SteamVR_TrackedController device;
  void Start() {
     device = GetComponent<SteamVR_TrackedController>();
     device.TriggerClicked += Trigger;
  }
  void Trigger(object sender, ClickedEventArgs e)
  {
     Debug.Log("Trigger has been pressed");
   }
}

ทอสอบหากคลิกปุ่มก็จะเกิด Debug.Log ว่า “Trigger has been pressed”

เช่นกันหากเราสร้าง Cube ขึ้นมาแล้วใส่ Component เพิ่มเข้าไปคือ Box Collider และ RigidBody ก็จะสามารถทำให้ Joy ของเรา Trigger แล้วหยิบจับ หรือโยนได้ Script สำหรับการหยิบจับวัตถุที่เป็น RigidBody ที่มี Collider คือ

using UnityEngine;

public class VRgetObjects: MonoBehaviour
{
   private SteamVR_TrackedObject trackedObject;
   private SteamVR_Controller.Device device;
   void Start(){
     trackedObject = GetComponent<SteamVR_TrackedObject>();
   }
   void Update(){
     device = SteamVR_Controller.Input((int)trackedObject.index);
     if(device.GetAxis().x != 0 || device.GetAxis().y != 0){
           	Debug.Log(device.GetAxis().x + " " + device.GetAxis().y);
     }
   }
}

ก็จะทำให้เราทราบว่าเราได้มีการ trackObject ได้ครับผ่าน

GetComponent<SteamVR_TrackedObject>();

หากใครที่ศึกษามาบ้างอยากใช้อะไรที่มากกว่าตัวอย่างข้างต้นครับ สามารถใช้ Script C# ของบริษัท RazeWare LLC. ได้ คือไฟล์

/*
 * Copyright (c) 2016 Razeware LLC
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

using UnityEngine;

public class ControllerGrabObject : MonoBehaviour
{
    private SteamVR_TrackedObject trackedObj;

    private GameObject collidingObject;
    private GameObject objectInHand;

    private SteamVR_Controller.Device Controller
    {
        get { return SteamVR_Controller.Input((int)trackedObj.index); }
    }

    void Awake()
    {
        trackedObj = GetComponent<SteamVR_TrackedObject>();
    }


    public void OnTriggerEnter(Collider other)
    {
        SetCollidingObject(other);
    }

    public void OnTriggerStay(Collider other)
    {
        SetCollidingObject(other);
    }

    public void OnTriggerExit(Collider other)
    {
        if (!collidingObject)
        {
            return;
        }

        collidingObject = null;
    }

    private void SetCollidingObject(Collider col)
    {
        if (collidingObject || !col.GetComponent<Rigidbody>())
        {
            return;
        }

        collidingObject = col.gameObject;
    }

    void Update()
    {
        if (Controller.GetHairTriggerDown())
        {
            if (collidingObject)
            {
                GrabObject();
            }
        }

        if (Controller.GetHairTriggerUp())
        {
            if (objectInHand)
            {
                ReleaseObject();
            }
        }
    }

    private void GrabObject()
    {
        objectInHand = collidingObject;
        collidingObject = null;
        var joint = AddFixedJoint();
        joint.connectedBody = objectInHand.GetComponent<Rigidbody>();
    }

    private FixedJoint AddFixedJoint()
    {
        FixedJoint fx = gameObject.AddComponent<FixedJoint>();
        fx.breakForce = 20000;
        fx.breakTorque = 20000;
        return fx;
    }

    private void ReleaseObject()
    {
        if (GetComponent<FixedJoint>())
        {
            GetComponent<FixedJoint>().connectedBody = null;
            Destroy(GetComponent<FixedJoint>());
            objectInHand.GetComponent<Rigidbody>().velocity = Controller.velocity;
            objectInHand.GetComponent<Rigidbody>().angularVelocity = Controller.angularVelocity;
        }

        objectInHand = null;
    }
}

แค่นี้เราก็สามารถทดสอบการ หยิบจับวัตถุภายใน Scene ของเราขว้าง วาง โยนได้แล้วครับ

บทเรียนต่อไปจะเป็นการแนะนำการใช้ Laser เพื่อ Teleport เดินไปมาครับ หวังว่าใครที่กำลังจะพัฒนาอยู่ก็น่าจะได้อะไรบ้างจากบทความนี้นะครับ

ขอขอบคุณผู้สนับสนุนอุปกรณ์ VR Headset HTC Vive สาขาการออกแบบเชิงโต้ตอบและการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ที่ให้อุปกรณ์มาทดสอบเพื่อรีวิวการทำ Tutorial สำหรับพัฒนาเกม VR ตัวนี้ครับ

ใครสนใจสมัครหลักสูตรนี้ก็ ที่นี่เลยครับ! http://ant.dpu.ac.th/index.php/gt/

สมัครที่: http://www.dpu.ac.th/applyform/ เลือก ANT

Asst. Prof. Banyapon Poolsawas

อาจารย์ประจำสาขาวิชาการออกแบบเชิงโต้ตอบ และการพัฒนาเกม วิทยาลัยครีเอทีฟดีไซน์ & เอ็นเตอร์เทนเมนต์เทคโนโลยี มหาวิทยาลัยธุรกิจบัณฑิตย์ ผู้ก่อตั้ง บริษัท Daydev Co., Ltd, (เดย์เดฟ จำกัด)

Related Articles

Back to top button

Adblock Detected

เราตรวจพบว่าคุณใช้ Adblock บนบราวเซอร์ของคุณ,กรุณาปิดระบบ Adblock ก่อนเข้าอ่าน Content ของเรานะครับ, ถือว่าช่วยเหลือกัน