4/30/2014

COOKBOOK - HIỂN THỊ BIỂU TƯỢNG CÁC MÓN ĐỒ ĐƯỢC NHẶT




Có rất nhiều loại đồ vật mà người chơi có thể nhặt và lưu trữ trong suốt quá trình chơi game như chìa khóa, bình máu, những món đồ tăng điểm.... Một lớp PickUp tổng quát để thực hiện chức năng nhặt những món đồ sẽ rất hữu dụng, và sử dụng GUI để hiển thị biểu tượng của các món đồ có thể được thực hiện thông qua code C# là List < T > để liệt kê các đối tượng.


Chuẩn bị

PickUp.rar


Cách để làm

B1. Vào File | New Project và đặt tên cho project mới là PickUp. Và đánh dấu vào ô Character Controller.





B2. Kéo thả 2 thư mục ảnh vừa tải ở phần Chuẩn bị về vào thẻ Project trong Unity.



B3. Tại thẻ Hierarchy, nhấp chọn nút Create | Terrain và qua thẻ Inspector điều chỉnh Position như hình dưới đây:



B4. Vẫn đang chọn Terrain ở thẻ Hierarchy, qua thẻ Inspector, điều chỉnh như hình sau:



B5. Tại thẻ Project, nhấp chọn nút Create | C# Script và đặt tên là PickUp. Double click vào file này và xóa tất cả đi rồi chèn đoạn code sau vào:

using UnityEngine;
using System.Collections;

public class PickUp : MonoBehaviour
{
    public enum PickUpCategory
    {
        KEY, HEALTH, SCORE
    }
   
    public Texture icon;
    public int points;
    public string fitsLockTag;
    public PickUpCategory catgegory;
   
}


B6. Kéo thả 3rd Person Controller trong thư mục Standard Assets | Character Controllers ở thẻ Project vào thẻ Hierarchy.



B7. Tạo file C# với tên là GeneralInventory và kéo thả file C# này vào 3rd Person Controller ở thẻ Project.

 using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GeneralInventory : MonoBehaviour
{
    const int ICON_HEIGHT = 32;
    private List<PickUp> inventory = new List<PickUp>();
  
    private void OnGUI()
    {
        // restrict display to left of screen
        Rect r = new Rect(0,0,Screen.width/2, ICON_HEIGHT);
        GUILayout.BeginArea(r);
        GUILayout.BeginHorizontal();
      
        DisplayInventory();
      
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();
        GUILayout.EndArea();
    }
  
    private void DisplayInventory()
    {
        foreach (PickUp item in inventory)
        {
            GUILayout.Label( item.icon );
        }
    }
  
    private void OnTriggerEnter(Collider hitCollider)
    {  
        if( "pickup" == hitCollider.tag )
        {
            PickUp item = hitCollider.GetComponent<PickUp>();
            inventory.Add( item );
            Destroy ( hitCollider.gameObject );
        }
    }
}


B8. Nhấp chọn 3rd Person Controller ở thẻ Hierarchy và qua thẻ Inspector điều chỉnh như sau:



B9. Tại thẻ Hierarchy, nhấp chọn nút Create | Cube và đặt tên là Cube-health. Kéo thả file C# PickUp ở thẻ Project vào Cube-health vừa tạo ở thẻ Hierarchy. Nhấp chọn Cube-health và qua thẻ Inspector điều chỉnh như sau:


B10. Thực hiện tương tự B9 để tạo ra các Cube-key và Cube-health với các icon khác nhau. Nhớ điều chỉnh Categories cho phù hợp nhé.


B11. Kéo thả các file ảnh pickup-items vào từng khối hộp để gán vật liệu cho chúng. VD: Cube-key có icon là key_yellow_icon thì kéo file key_yellow làm vật liệu.


B12. Nhấn nút Play để kiểm tra thành quả.


Nguyên lí làm việc

Lớp PickUp không chứa hàm nhưng nó bao gồm nhiều biến public hữu dụng. Nó còn có một kiểu dữ liệu liệt kê - enum để phân loại đồ vật thành 3 nhóm là: KEY, HEALTH và SCORE. Mỗi đồ vật được lớp PickUp định nghĩa với một biểu tượng, một điểm số nguyên, một chuỗi (cho mỗi món đồ chìa khóa, tag ), và tùy theo món đồ vật mà nó sẽ được xếp vào mỗi mục phân loại đồ vật khác nhau.

Các đối tượng trong game đều được gắn script PickUp. Trong bài viết này, những khối hộp với các hình ảnh để mô tả phân loại đồ vật của chúng, nhưng các đồ vật người chơi gặp trong thế giới game có thể các món đồ tương tác ba chiều hoặc bất kể là gì. Mỗi món đồ trong game với script PickUp cần điều chỉnh thuộc tính một cách thích hợp. Ví dụ như, chìa khóa màu vàng phải có biểu tượng là chìa khóa màu vàng, được đặt category là KEY và phải đặt Fits Lock Tag là chiếc rương mà nó có thể mở.

Nhân vật của người chơi được gắn script GeneralInventory. Script này sử dụng GUI với 2 hàm chính: đầu tiên là List<T> thu nhận thông tin các món đồ vật được người chơi đang có, và hiển thị ra màn hình các biểu tượng của từng món đồ đó thông qua hàm OnGUI. Hàm chính thứ hai là để kiểm tra va chạm với đồ vật có thể nhặt thông qua hàm OnTriggerEnter, và mỗi đối tượng được đặt tag là pickup khi va chạm sẽ được thêm vào danh sách hành trang.


Còn nữa

Các đồ vật được nhặt nhưng không hiển thị

Với các mục phân loại đồ vật khác nhau, việc xử lý khi va chạm cũng sẽ khác nhau. Như việc người chơi nhặt được món đồ Health thì điểm sẽ được cộng vào máu của người chơi và khi đó món đồ sẽ bị mất đi thay vì được thêm vào hành trang. Việc này cần dùng đến hàm If trong hàm OnTriggerEnter để quyết định sẽ làm gì khi một món đồ được nhặt.

Xóa món đồ từ danh sách nhặt List<>

Khi bạn mở một cánh cửa cần chìa khóa thì chiếc chìa khóa trong hành trang bạn phải mất sau khi đã mở, vì vậy bạn cần phải xóa nó ra khỏi danh sách hành trang. Để thực hiện điều này, bạn sẽ cần dùng đến hàm If bên trong hàm OnTriggerEnter để phát hiện va chạm. Ở đây mình sử dụng chìa khóa vàng để mở cửa và xóa nó ra khỏi danh sách hành trang.






if( "yellowDoor" == hitCollider.tag )
    OpenDoor(hitCollider.gameObject);


Hàm OpenDoor sẽ cần được khai báo món đồ nào trong danh sách có thể mở được cửa và nếu tìm thấy món đồ đó sẽ xóa nó khỏi danh sách hành trang. Sau đó cửa sẽ mở thông qua hàm sau:

     private void OpenDoor(GameObject doorGO)
    {
        // search for key to open the tag of doorGO
        int colorKeyIndex = FindItemIndex(doorGO.tag);
        if( colorKeyIndex > -1 )
        {
            // remove key item
            inventory.RemoveAt( colorKeyIndex );
          
            // now open the door ...
            doorGO.animation.Play ("open");
        }
    }
  
    private int FindItemIndex(string doorTag)
    {
        for (int i = 0; i < inventory.Count; i++)
        {
            PickUp item = inventory[i];
            if( item.fitsLockTag == doorTag )
                return i;
        }
      
        // not found, return -1
        return -1;
    }

No comments:

Post a Comment