9/30/2014

AI 4 - Cài đặt Giác quan


  AI 4 - Cài đặt giác quan -

Đây là một chương ngắn về cách thực hiện hành vi AI sử dụng các khái niệm về một hệ thống cảm giác tương tự như những gì thực thể sống có. Như chúng ta đã thảo luận trước đó, một hệ thống nhân vật AI cần phải có nhận thức về môi trường, nhận thức các trường hợp trở ngại, nơi kẻ thù nó đang tìm kiếm, nếu đối phương có thể bị phát hiện trong tầm nhìn của người chơi, và những cái khác. Chất lượng trí tuệ nhân tạo của NPC của chúng ta hoàn toàn phụ thuộc vào thông tin mà nó có thể nhận được từ môi trường. Dựa trên thông tin đó, các nhân vật AI sẽ quyết định logic để thực hiện. Nếu không có đủ thông tin cho AI, nhân vật AI của chúng ta có thể có các hành vi kỳ lạ, chẳng hạn như việc lựa chọn địa điểm sai để hỗ trợ, ngủ, và vòng lặp hành động kỳ lạ, và không biết những gì để đưa ra quyết định thực hiện. Thử tìm kiếm "AI glitches" trên YouTube, và bạn sẽ tìm thấy một số hành vi hài hước của nhân vật AI ngay cả trong trò chơi AAA.



Chúng ta có thể phát hiện tất cả các thông số môi trường và kiểm tra lần nữa đối với các giá trị được xác định trước của chúng ta nếu chúng ta muốn. Nhưng sử dụng một mẫu thiết kế phù hợp sẽ giúp chúng ta duy trì mã và do đó sẽ dễ dàng mở rộng. Chương này sẽ giới thiệu như một mẫu thiết kế mà chúng ta có thể sử dụng để thực hiện các hệ thống giác quan. Chúng ta sẽ được đi qua những gì một hệ thống cảm giác phải là, và làm thế nào để thực hiện một hệ thống như vậy trong Unity. Sau đó chúng ta sẽ xây dựng một bản demo mà chúng ta có thể thấy về hệ thống cảm giác của chúng ta trong hành động.


Hệ thống giác quan cơ bản 

Các hệ thống cảm giác AI tranh nhau cảm nhận như nhìn, âm thanh, và thậm chí cả mùi hương để theo dõi và xác định đối tượng. Trong trò chơi hệ thống giác quan AI, các đại lý sẽ phải kiểm tra môi trường và kiểm tra các giác quan định kỳ dựa trên lợi ích cụ thể của mình.

Khái niệm về một hệ thống cảm giác cơ bản có hai thành phần: Hình thể và Giác quan. Nhân vật AI của chúng ta sẽ có giác quan, chẳng hạn như thị giác, khứu giác, và xúc giác. Các giác quan này sẽ tìm thấy các hình thể cụ thể như kẻ thù và tên cướp. Ví dụ, bạn có thể có một người bảo vệ tuần tra AI có một thị giác để tìm kiếm các đối tượng trò chơi khác cùng hình thể của một kẻ địch. Hoặc nó có thể là một thực thể zombie với một khứu giác tìm kiếm các thực thể khác có một hình thể được định nghĩa như bộ não.


Trong demo của chúng ta, điều này về cơ bản là những gì chúng ta sẽ thực hiện: một giao diện cơ bản được gọi là Sense sẽ được thực hiện bằng các giác quan tùy chỉnh khác. Trong chương này, chúng ta sẽcài đặt thị giác và xúc giác.

Xúc giác là những gì động vật sử dụng để nhìn thấy thế giới xung quanh. Nếu nhân vật AI của chúng ta nhìn thấy một kẻ thù, chúng ta muốn được thông báo để mà chúng ta có thể có một số hành động. Tương tự như vậy, với xúc giác, khi kẻ thù đến quá gần, chúng ta muốn có thể cảm nhận được; gần như là nếu nhân vật AI của chúng ta có thể nghe thấy rằng kẻ thù đang ở gần đó. Vậy thì chúng ta sẽ viết một lớp Aspect cho giác quan về việc tìm kiếm.

RAIN{ONE} là một phần mềm AI tích hợp cho Unity3D, hỗ trợ nhiều về hệ thống giác quan mà không cần phải code nhiều.

Đoạn trích dưới đây RAIN đã được lấy từ http://rivaltheory.com/product:

RAIN tăng thanh cho AI trong Unity bằng cách cho nhân vật trong game khả năng cảm nhận thế giới, tìm đường, thực hiện hành vi cây tinh vi, và sửa đổi hành động dựa trên đặc điểm tính cách. Tất cả điều này thậm chí có thể được thực hiện với người có ít hoặc không có kinh nghiệm code.

Thiết lập scene

Source code bài này mình đặt ở dưới phần tóm tắt!!

Hãy bắt đầu thiết lập scene của chúng ta. Đầu tiên chúng ta hãy tạo ra một vài bức tường để ngăn chặn tầm nhìn từ nhân vật AI của chúng ta với kẻ thù. Nó ngắn nhưng hình khối rộng được nhóm theo một đối tượng game được gọi là Obstacles. Tiếp theo, chúng ta thêm một chiếc máy bay được sử dụng như một tầng. Sau đó, chúng ta thêm một đường ánh sáng, thế là chúng ta có thể nhìn thấy những gì đang diễn ra trong scene của chúng ta rồi.

Chúng ta sẽ đi qua phần tiếp theo này một cách chi tiết trong suốt chương, nhưng về cơ bản, chúng ta sẽ sử dụng một mô hình xe tăng đơn giản cho người chơi của chúng ta, và một khối lập phương đơn giản cho nhân vật AI của chúng ta. Chúng ta cũng sẽ có một đối tượng Target để chỉ cho chúng ta nơi xe tăng sẽ di chuyển đến trong scene của chúng ta. Hệ thống cấp bậc scene của chúng ta sẽ trông giống như hình bên dưới:


Bây giờ chúng ta sẽ định vị xe tăng, nhân vật AI, và các bức tường xung quanh một cách ngẫu nhiên trong scene. Tăng kích thước của máy bay để có tầm nhìn tốt hơn. May mắn thay, trong bản demo này, các đối tượng của chúng ta đều nổi, vì vậy không có gì sẽ rơi ra khỏi máy bay. Ngoài ra hãy chắc chắn việc điều chỉnh camera để chúng ta có thể có một cái nhìn rõ ràng như sau đây:


Bây giờ chúng ta có những điều cơ bản đã được thiết lập, chúng ta sẽ xem làm thế nào để thực thi các xe tăng, nhân vật AI, và các hình thể cho nhân vật của người chơi.


Xe tăng và Hình thể

Mục tiêu của chúng ta là một vật thể hình cầu đơn giản với lưới không kích hoạt. Chúng ta cũng đã tạo ra một điểm ánh sáng và biến nó thành một đứa con của mục tiêu chúng ta. Hãy chắc chắn rằng ánh sáng tập trung, hoặc nó sẽ không còn có thể quá hữu ích cho chúng ta.

Nhìn vào đoạn mã sau đây trong tập tin Target.cs:

using UnityEngine;
using System.Collections;
public class Target : MonoBehaviour {
  public Transform targetMarker;
  void Update () {
    int button = 0;
    //Get the point of the hit position when the mouse is being
// clicked.
    if (Input.GetMouseButtonDown(button)) {
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      RaycastHit hitInfo;
      if (Physics.Raycast(ray.origin, ray.direction, out hitInfo)) {
        Vector3 targetPosition = hitInfo.point;
        targetMarker.position = targetPosition;
      }
    }
  }
}

Đính kèm đoạn script này vào đối tượng Target của chúng ta. Script phát hiện các sự kiện click chuột và sau đó, sử dụng kỹ thuật raycasting, phát hiện điểm click chuột trên máy bay trong không gian 3D. Sau đó nó cập nhật các đối tượng mục tiêu vào vị trí đó trong scene của chúng ta.


Xe tăng người chơi

Xe tăng người chơi là một mô hình xe tăng đơn giản, chúng ta đã sử dụng trong chương trước với một thành phần bộ xương cứng nhắc không chuyển động. Thành phần bộ xương cứng nhắc là cần thiết để tạo ra các sự kiện kích hoạt bất cứ khi nào chúng ta làm phát hiện va chạm với bất kỳ nhân vật AI nào. Điều đầu tiên chúng ta cần làm là gán nhãn Player vào xe tăng của chúng ta.

Xe tăng được điều khiển bởi một đoạn script PlayerTank, mà chúng ta sẽ tạo ra trong một thời điểm. Đoạn script này lấy vị trí mục tiêu trên bản đồ, và cập nhật điểm đích của nó và hướng phù hợp.

Các mã trong tập tin PlayerTank.cs được thể hiện như sau:

using UnityEngine;
using System.Collections;
public class PlayerTank : MonoBehaviour {
  public Transform targetTransform;
  private float movementSpeed, rotSpeed;
  void Start () {
    movementSpeed = 10.0f;
    rotSpeed = 2.0f;
  }
  void Update () {
    //Stop once you reached near the target position
    if (Vector3.Distance(transform.position,
      targetTransform.position) < 5.0f)
      return;
    //Calculate direction vector from current position to target
//position
    Vector3 tarPos = targetTransform.position;
    tarPos.y = transform.position.y;
    Vector3 dirRot = tarPos - transform.position;
    //Build a Quaternion for this new rotation vector
    //using LookRotation method
    Quaternion tarRot = Quaternion.LookRotation(dirRot);

    //Move and rotate with interpolation
    transform.rotation= Quaternion.Slerp(transform.rotation,
        tarRot, rotSpeed * Time.deltaTime);
    transform.Translate(new Vector3(0, 0,
        movementSpeed * Time.deltaTime));
  }
}




Đoạn script này lấy vị trí của đối tượng Target trên bản đồ, và cập nhật điểm đích của nó và hướng phù hợp. Sau khi chúng ta gán đoạn script này vào xe tăng của chúng ta, hãy chỉ định đối tượng Target của chúng ta vào biến targetTransform.


Hình thể

Tiếp theo, chúng ta hãy nhìn vào lớp Aspect.cs. Hình thể là một lớp rất đơn giản chỉ với một thuộc tính public gọi là aspectName. Đó là tất cả các biến chúng ta cần trong chương này. Bất cứ khi nào nhân vật AI của chúng ta cảm nhận được một cái gì đó, chúng ta sẽ kiểm tra đối với aspectName này nếu đó là hình thể mà AI đang tìm kiếm.

Các mã trong tập tin Aspect.cs được thể hiện như sau:

using UnityEngine;
using System.Collections;
public class Aspect : MonoBehaviour {
  public enum aspect {
    Player,
    Enemy
  }
  public aspect aspectName;
}

Đính kèm đoạn script này vào player tank, và thiết lập thuộc tính aspectName thành Enemy.



Nhân vật AI

Nhân vật AI của chúng ta sẽ được chuyển vùng xung quanh scene theo một hướng ngẫu nhiên. Nó sẽ có hai giác quan: thị giác và xúc giác. Thị giác sẽ kiểm tra xem các hình thể của đối phương nằm trong một phạm vi có thể nhìn thấy và một khoảng cách thiết lập. Xúc giác sẽ phát hiện nếu các hình thể kẻ thù đã va chạm với chiếc hộp, sớm được vây xung quanh nhân vật AI của chúng ta. Như chúng ta đã thấy trước đây, player tank của chúng ta sẽ có hình thể Enemy. Vì vậy, các giác quan sẽ được kích hoạt khi phát hiện các player tank.

Các mã trong tập tin Wander.cs có thể được hiển thị như sau:

using UnityEngine;
using System.Collections;
public class Wander : MonoBehaviour {
  private Vector3 tarPos;
  private float movementSpeed = 5.0f;
  private float rotSpeed = 2.0f;
  private float minX, maxX, minZ, maxZ;
  // Use this for initialization
  void Start () {
    minX = -45.0f;
    maxX = 45.0f;
    minZ = -45.0f;
    maxZ = 45.0f;
    //Get Wander Position
    GetNextPosition();
  }

  // Update is called once per frame
  void Update () {
    // Check if we're near the destination position
    if (Vector3.Distance(tarPos, transform.position) <= 5.0f)
      GetNextPosition(); //generate new random position
    // Set up quaternion for rotation toward destination
    Quaternion tarRot = Quaternion.LookRotation(tarPos -
        transform.position);
    // Update rotation and translation
    transform.rotation = Quaternion.Slerp(transform.rotation, tarRot,
        rotSpeed * Time.deltaTime);
    transform.Translate(new Vector3(0, 0,
        movementSpeed * Time.deltaTime));
  }

  void GetNextPosition() {
    tarPos = new Vector3(Random.Range(minX, maxX), 0.5f,
        Random.Range(minZ, maxZ));
  }
}

Đoạn script Wander tạo ra một vị trí ngẫu nhiên mới trong một phạm vi chỉ định bất cứ khi nào nhân vật AI bước vào điểm đích hiện tại của nó. Phương thức Update khi đó sẽ xoay về kẻ thù của chúng ta, và di chuyển nó đến đích mới này. Đính kèm đoạn script này vào nhân vật AI của chúng ta để nó có thể di chuyển xung quanh trong scene.


Lớp giác quan Sense

Lớp Sense là giao diện của hệ thống giác quan của chúng ta mà các giác quan tùy chỉnh khác có thể thực thi. Nó định nghĩa hai phương thức ảo, Initialize và UpdateSense, sẽ được thực hiện trong các giác quan tùy chỉnh, và được thực hiện từ các phương thức Start và Update tương ứng.
Các mã trong tập tin Sense.cs có thể được hiển thị như sau:

using UnityEngine;
using System.Collections;
public class Sense : MonoBehaviour {
  public bool bDebug = true;
  public Aspect.aspect aspectName = Aspect.aspect.Enemy;
  public float detectionRate = 1.0f;
  protected float elapsedTime = 0.0f;
  protected virtual void Initialize() { }
  protected virtual void UpdateSense() { }
  // Use this for initialization
  void Start () {
    elapsedTime = 0.0f;
    Initialize();
  }

  // Update is called once per frame
  void Update () {
    UpdateSense();
  }
}


Perspective

Thị giác sẽ phát hiện xem một hình thể cụ thể có nằm trong phạm vi tầm nhìn của mình và khoảng cách có thể thấy được. Nếu nó thấy bất cứ điều gì, nó sẽ có những hành động cụ thể.

Các mã trong tập tin Perspective.cs có thể được hiển thị như sau:

using UnityEngine;
using System.Collections;

public class Perspective : Sense {
  public int FieldOfView = 45;
  public int ViewDistance = 100;
  private Transform playerTrans;
  private Vector3 rayDirection;
  protected override void Initialize() {
    //Find player position
    playerTrans =
   
  GameObject.FindGameObjectWithTag("Player").transform;
  }
  // Update is called once per frame
  protected override void UpdateSense() {
    elapsedTime += Time.deltaTime;
    // Detect perspective sense if within the detection rate
    if (elapsedTime >= detectionRate) DetectAspect();
  }
  //Detect perspective field of view for the AI Character
  void DetectAspect() {
    RaycastHit hit;
    //Direction from current position to player position
    rayDirection = playerTrans.position -
        transform.position;
    //Check the angle between the AI character's forward
    //vector and the direction vector between player and AI
    if ((Vector3.Angle(rayDirection, transform.forward)) <
FieldOfView) {
      // Detect if player is within the field of view
      if (Physics.Raycast(transform.position, rayDirection,
          out hit, ViewDistance)) {
        Aspect aspect =
        hit.collider.GetComponent<Aspect>();
        if (aspect != null) {
          //Check the aspect
          if (aspect.aspectName == aspectName) {
            print("Enemy Detected");
          }
        }
      }
    }
  }

Chúng ta cần phải thực hiện phương thức Initialize và UpdateSense  được gọi từ Start và Update từ lớp cha Sense. Sau đó, trong phương thức DetectAspect, trước tiên chúng ta kiểm tra các góc giữa người chơi và hướng hiện tại của AI. Nếu nằm trong phạm vi tầm nhìn, chúng ta bắn một tia theo hướng vị trí của người chơi. Chiều dài tia là giá trị khoảng cách tầm nhìn. Phương thức Raycast sẽ trả lại giá trị trong lần đầu tiên truy cập đối tượng khác. Sau đó, chúng ta sẽ kiểm tra đối với các thành phần hình thể và tên hình thể. Bằng cách này, ngay cả khi các người chơi nằm trong phạm vi có thể nhìn thấy, nhân vật AI sẽ không thể thấy nếu nó ẩn đằng sau bức tường.

Phương thức OnDrawGizmos vẽ ra các đường dựa trên các vùng thị giác của góc nhìn và khoảng cách tầm nhìn, để chúng ta có thể thấy tầm nhìn của nhân vật AI trong cửa sổ soạn thảo suốt quá trình test. Đính kèm đoạn script này vào nhân vật AI của chúng ta, và chắc chắn rằng tên hình thể được thiết lập là Enemy.

Phương thức này có thể được minh họa như sau:

  void OnDrawGizmos() {
    if (!bDebug || playerTrans == null) return;
    Debug.DrawLine(transform.position, playerTrans.position, Color.
red);
    Vector3 frontRayPoint = transform.position +
        (transform.forward * ViewDistance);
    //Approximate perspective visualization
    Vector3 leftRayPoint = frontRayPoint;
    leftRayPoint.x += FieldOfView * 0.5f;
    Vector3 rightRayPoint = frontRayPoint;
    rightRayPoint.x -= FieldOfView * 0.5f;
    Debug.DrawLine(transform.position, frontRayPoint, Color.green);
    Debug.DrawLine(transform.position, leftRayPoint, Color.green);

    Debug.DrawLine(transform.position, rightRayPoint, Color.green);
  }
}



Xúc giác

Một giác quan khác mà chúng ta sẽ thực hiện là Touch.cs, được kích hoạt khi thực thể người chơi nằm trong một vài khu vực nhất định gần thực thể AI. Nhân vật AI của chúng ta có một thành phần hộp va chạm, cờ Trigger được bật lên. Chúng ta cần phải thực hiện OnTriggerEnter dù rằng sẽ bị mất bất cứ khi nào các thành phần va chạm với một thành phần va chạm khác. Kể từ khi thực thể xe tăng của chúng ta cũng có một thành phần xung đột và bộ xương cứng nhắc, các sự kiện va chạm sẽ được đưa ra ngay sau khi va chạm giữa các nhân vật AI và xe tăng người chơi.

Code trong tập tin Touch.cs có thể viết như sau:

using UnityEngine;
using System.Collections;
public class Touch : Sense {
  void OnTriggerEnter(Collider other) {
    Aspect aspect = other.GetComponent<Aspect>();
    if (aspect != null) {
      //Check the aspect
      if (aspect.aspectName == aspectName) {
        print("Enemy Touch Detected");
      }
    }
  }
}

Chúng ta thực hiện các sự kiện OnTriggerEnter bị loại bỏ bất cứ khi nào các thành phần collider được va chạm với một thành phần collider khác. Kể từ khi thực thể xe tăng của chúng ta cũng là một collider và các thành phần khung xương cứng nhắc, các sự kiện va chạm sẽ được đưa ra ngay khi các collider của các nhân vật AI và xe tăng người chơi va chạm vào nhau.


Các con số trên cho thấy các hộp collider của kẻ thù AI của chúng ta, mà chúng ta sẽ sử dụng để thực hiện xúc giác. Trong hình bên dưới, chúng ta thấy việc cài đặt nhân vật AI  của chúng ta.


Trong phương thức OnTriggerEnter, chúng ta truy cập vào các thành phần hình thể của thực thể va chạm khác và kiểm tra xem tên của các hình thể mà hình thể nhân vật AI này đang tìm kiếm. Và, với mục đích giới thiệu, chúng ta chỉ in ra các hình thể của đối phương đã bị phát hiện bởi xúc giác. Chúng ta cũng có thể thực hiện các hành vi khác nếu trong dự án thực tế; có lẽ các người chơi sẽ kết thúc một kẻ thù và bắt đầu đuổi theo, tấn công, và như vậy.


Thử nghiệm 

Chơi các trò chơi trong Unity3D, và di chuyển các xe tăng người chơi gần nhân vật AI đang lang thang bằng cách nhấn vào mặt đất. Bạn sẽ thấy Enemy cảm nhận ngay việc tín hiệu được phát hiện trong cửa sổ giao diện điều khiển đăng nhập bất cứ khi nào nhân vật AI của chúng ta tiến đến gần xe tăng người chơi của chúng ta.


Các con số trên cho thấy một agent AI có cảm ứng và thị giác đang tìm kiếm một hình thể kẻ thù. Di chuyển các xe tăng người chơi ở phía trước nhân vật AI, và bạn sẽ nhận được thông điệp phát hiện Enemy. Nếu bạn đi đến tầm nhìn biên tập trong khi chạy trò chơi, bạn sẽ thấy các bản vẽ debug trả lại. Điều này là do các phương thức OnDrawGizmos thực hiện trong lớp tầm nhìn của Sense.


Source code

 
Tóm tắt 

Chương này giới thiệu các khái niệm về sử dụng cảm biến trong việc thực hiện trò chơi AI, và cài đặt hai giác quan, thị giác và xúc giác, cho nhân vật AI của chúng ta. Hệ thống cảm giác chỉ là một phần của hệ thống ra quyết định của toàn bộ hệ thống AI. Chúng ta có thể sử dụng hệ thống cảm giác kết hợp với một hệ thống hành vi để thực hiện hành vi nhất định cho các giác quan nhất định. Ví dụ, chúng ta có thể sử dụng một FSM để thay đổi để đuổi theo và tấn công các trạng thái từ các trạng thái tuần tra một khi chúng ta đã phát hiện ra rằng có một kẻ thù trong tầm nhìn. Chúng tôi cũng sẽ giới thiệu làm thế nào để áp dụng hệ thống cây hành vi trong Chương 9, Cây hành vi. Trong chương tiếp theo, chúng tôi sẽ xem làm thế nào để thực hiện hành vi đổ trong Unity3D, cũng như làm thế nào để thực hiện thuật toán đổ Craig Reynold.


8 comments:

  1. Copy bài viết và dịch lại một cách hời hợt.

    ReplyDelete
  2. Game mới, hướng dẫn cài đặt, hướng dẫn chơi quá rõ ràng luôn, còn chần chờ gì mà không thử các bạn ơi. Cảm ơn admin đã có bài hướng dẫn cụ thể và chia sẻ thông tin này.
    ------------------------------------
    Đầu thu xem VTV3 HD và hơn 68 kênh miễn phí thuê bao

    Liên hệ: 0909 480 368 – 08 7303 1368

    Chuyên bán: Đầu thu DVB T2 chính hãng.
    Xem tổng thể tại: Đầu thu kỹ thuật số

    ReplyDelete
  3. Bạn có đặt liên kết với blog mình không ?
    Blog mình là:
    voccode.blogspot.com

    ReplyDelete
  4. Thế mới thấy, để viết được 1 game đồ họa cao ko phải là điều dễ dàng gì.
    ---------------------------------------
    Jetstar khuyến mãi: Ba tiếng mỗi ngày – Thỏa ước mơ bay! với giá vé chỉ từ 11.000đ tất cả các ngày trong tuần. Chương trình áp dụng cho các đường bay nội địa và quốc tế.

    Xem thêm về Jetstar: Giá vé máy bay Jetstar | Săn vé máy bay giá rẻ đi Sài Gòn | Đặt vé Jetstar giá rẻ

    ReplyDelete
  5. Quá hay. Với công nghệ này, người chơi có thể cảm giác trò chơi y như thật.
    ------------------------------------
    Kingtek - Đầu thu kỹ thuật số xem miễn phí các kênh HTV7, HTV9, VTV3 HD, VTV1 HD, Let's Viet, nhóm kênh VTC và hơn 68 kênh miễn phí thuê bao khác.

    Liên hệ: 0909 480 368 – 08 7303 1368 để biết thêm chi tiết.

    Kingtek - Đơn vị uy tín chuyên phân phối: Đầu thu DVB T2 chính hãng.
    Xem thêm: Danh sách các kênh thu được từ đầu thu kỹ thuật số

    ReplyDelete
  6. Tham gia chơi game danh bai đổi thẻ điện thoại uy tín nhất Việt Nam. Trải nghiệm game Tien Len Mien Nam hoàn toàn mới trên hệ thống BaiVip.Net

    ReplyDelete