Bài toán tìm đường đi trong Unity

Các bạn đã từng chơi game dota hay lol thì cũng để ý làm sao con quái có thể tự tìm đường đi đến 1 điểm mà trên đường đi có các cây cối, block đường các thứ. Con quái phải né tránh và tìm đường tối ưu đến với đích. Vậy bình thường ta sẽ xây dựng thuật toán tìm đường cho nó ví dụ như A ,. Nhưng bài toán đặt ra là nếu bạn làm cho nhiều loại quái với các kiểu đi khác nhau cũng như bị block đường bởi các đối tượng khác nhau. Vậy thì sẽ phải code nhiều thêm cho từng loại quái đó. May mắn là trong Unity đã cung cấp cho chúng tôi Navigation xử lý điều này. Đầu tiên, mình đi vào tổng quan về Navigation với các khái niệm:

  • NavMesh: Cấu trúc data cho việc tìm đường đi cho đối tượng.
  • NavMesh Agent: Component giúp bạn tạo di chuyển cho đối tượng kết hợp với NavMesh.
  • Off-Mesh Link: Component cho phép di chuyển tắt qua nhau mà không theo quy luật Navigation bình thường là phải qua từng điểm một.
  • NavMesh Obstacle: Component mô tả đối tượng nào bị tránh khi trên đường di chuyển. (Xem thêm: https://docs.unity3d.com/Manual/Navigation.html)

Giờ mình bắt tay vào làm demo sử dụng Navigation:

  • Đầu tiên: mình tạo 1 map như hình
  • Sau khi tạo xong, mở cửa sổ Navigation từ Windows menu. Chọn All và tích Navigation Static nghĩa là các đối tượng này không di chuyển trong suốt run time.
  • Rồi chuyển tab Bake, như hình các layer màu xanh đó biểu thị cho những vị trí được đi qua.
  • Mình có thể thay đổi vị trí đi qua bằng cách tham đổi các biến số trong Bake tab.
  • Giờ mình đã tạo được map với các NavMesh cơ bản rồi. Tiếp đến, chọn đối tượng di chuyển để thêm NavMesh Agent component và mình có thể tùy chỉnh các thông số ở đây cho thích hợp.
  • Bước cuối cùng chỉ là tạo cho đối tượng để di chuyển nữa là xong. Mình tạo script EnemyMovement.cs và add vào đối tượng với code:
using UnityEngine;
using System.Collections;
using UnityEngine.AI;

public class EnemyMovement : MonoBehaviour
{
    Transform player;
    // Reference to the player's position.

    NavMeshAgent nav;
    // Reference to the nav mesh agent.

    void Awake ()
    {
        // Set up the references.
        player = GameObject.FindGameObjectWithTag ("Player").transform; 

        // Do not use FindGameObjectWithTag() method if the scene hierarchy is too big. 
        // In such case, declare 'player' as a public variable & set reference from the inspector.

        nav = GetComponent <NavMeshAgent> ();
    }

    void Update ()
    {
        // Set the destination of the nav mesh agent to the player.
        nav.SetDestination (player.position);
    }
}

Hàm nav.SetDestination (player.position) cho phép đối tượng luôn di chuyển để player và tự động tránh các vật cản trên đường.

Như vậy là mình vừa tạo xong di chuyển với Navigation cho đối tượng sau chưa đầy 10 phút nhanh hơn rất nhiều so với chúng ta code thuật toán tìm được. Và bài viết mình tới đây là kết thúc rồi. Cảm ơn bạn đã đọc tới đây. Hẹn gặp lại ^^! p/s: Bài viết này có tham khảo từ http://www.theappguruz.com/blog/learn-unity-navigation-using-navmesh