Tìm hiểu về Steering Behaviors (Phần 5) - Obstacle Avoidance
Unity
7
White

Kaopiz Software Co., Ltd. viết ngày 28/03/2019

Tiếp nối series tìm hiểu về Steering Behaviors, lần này sẽ là một behavior giúp ích rất nhiều cho những những behavior đã giới thiệu. Đó là tránh đi những vật cản. Tất cả những behavior mà em đã giới thiệu kết hợp với behavior này khiến cho những con bot trở nên rất thật.

Lưu ý

Có một số cần lưu ý về behavior này.:

  • Thứ nhất là nó khác so với tài liệu nguồn của tác giả Fernando Bevilacqua tại phần 1. Vì tác giả của tài liệu này sử dụng cái mà em cho rằng không tối ưu lắm cho cách mà Unity hoạt động cái này sẽ nói sau.
  • Thứ 2 là do em quen sử dụng raycast cho object 3D hơn là 2D nên tại phần này sẽ sử dụng collider của object 3D để hoạt động, phần này hoàn toàn dễ dàng đổi sang 2D được.

Không để dài dòng nữa sau đây là cách mà behavior này được thực hiện trong Unity.

Khái niệm

Vấn đề cốt lõi của behavior này là sử dụng velocity hiện tại của Steering agent để có thể dự đoán được phía trước có vật cả hay không, để làm điều này ta sử dụng Physics.Raycast của Unity như sau
Physics.Raycast(transform.position, new Vector3(velocity.x, velocity.y), out hit, distance, obstacleMask)
trong hàm này thì param thứ nhất là vị trí cast ray, param thứ 2 là hướng của tia ray, out hit là kết quả trả ra, distance là độ dài của ray và obstacleMask là layer mask của những Object mà ta coi là vật cản.

Vật cản (Obstacle)

Cơ bản thì vật cản cần có những thuộc tính sau: alt text
Không cần để ý đến Animation làm gì cả hay chú ý đến Layer và Sphere Collider vì Physics.Raycast sẽ nhận diện collider của object 3D và Physics.Raycast2D sẽ nhận diện collider của object 2D (Circle Collider). Để cho thực sự tối ưu của behavior này mọi người nên dùng Sphere hoặc Circle để làm Collider cho vật cản thay vì những loại collider khác vì hình tròn dễ tính toán nhất :v

Steering Bot

Vật là thiết lập xong phần vật cản, sau đây sẽ sang tiêt mục chính:
Vector2 obstacleAvoidance()
{
Vector2 steering = Vector2.zero;
RaycastHit hit;
if (Physics.Raycast(transform.position, new Vector3(velocity.x, velocity.y), out hit, 5, obstacleMask))
{
Vector3 diff = transform.position - hit.collider.gameObject.transform.position;
steering += new Vector2(diff.x, diff.y);
}
steering = steering.normalized * max_avoid;
return steering;
}

Nhìn khác là quen thuộc như những behavior khác phải không. Đầu tiên chúng ta cần đầu ra cho Physics.Raycast đó là RaycastHit object, object này sẽ chứa toàn bộ thông tin physics của object mà Raycast chạm phải.
Sau khi "bắn" tia và nó chạm phải cài gì đó, tính toán chiều cần rẽ bằng cách tính diff như trên, thực ra thì nó giống như evade behavior thôi.
Cuối cùng tính độ lớn để có thể cộng vào steering tổng trong Update
Như vậy là xong rồi
Trong Update của obstacleAvoidance sẽ có steeringForce như sau:
steeringForce = steeringForce + obstacleAvoidance() + seek(Camera.main.ScreenToWorldPoint(Input.mousePosition));
Con bot này sẽ đuổi theo chuột và luôn tránh những vật cản trước nó như sau: alt text

Khá là đơn giản phải không! Tại đây em có sử dụng thêm hàm Debug.DrawRay(transform.position, new Vector3(velocity.x, velocity.y) * 1, Color.white); để show lên làm hình velocity hiện tại của con bot để hiểu rõ về cách mà behavior này hoạt động.

Ngoài lề

Nói về thuật toán của tác giả Fernando Bevilacqua, tác giả sử dụng việc tìm ra vật cản gần nhất bằng hàm
function findMostThreateningObstacle() :Obstacle {
var mostThreatening :Obstacle = null;
for (var i:int = 0; i < Game.instance.obstacles.length; i++) {
var obstacle :Obstacle = Game.instance.obstacles[i];
var collision :Boolean = lineIntersecsCircle(ahead, ahead2, obstacle);
// "position" is the character's current position
if (collision && (mostThreatening == null || distance(position, obstacle) < distance(position, mostThreatening))) {
mostThreatening = obstacle;
}
}
return mostThreatening;

Tuy hàm không viết bằng C# nhưng cũng nhìn ra được thuật toán sử dụng một vòng lặp tìm ra vật cản trong một list những vật cản, và bằng điều này dùng cho nhiều bot sẽ khiến cho thuật toán tính toán chậm đi rất nhiều.


Bài viết này được trích dẫn từ blog nội bộ công ty KAOPIZ - カオピーズ
Bài gốc: http://kipalog.kaopiz.com/posts/BpLtr8zgvmqpLLQquiVMag

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Kaopiz Software Co., Ltd.

27 bài viết.
24 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
50 2
Bài viết này được trích dẫn từ blog nội bộ công ty (Link) (Link) Bài gốc: https://kipalog.kaopiz.com/posts/RegexHocroimanhuchuahoc (Ảnh) 1. Tự...
Kaopiz Software Co., Ltd. viết 9 tháng trước
50 2
White
5 0
Mở Đầu Chắc hẳn là dev ai cũng từng nghe qua về Docker và Virtual Machine (VBox hoặc Vmware). Docker giúp cho việc xây dựng và triển khai một môi ...
Kaopiz Software Co., Ltd. viết 9 tháng trước
5 0
White
5 0
Introduction Elasticsearch là một công cụ tìm kiếm dựa trên nền tảng Apache Lucene. Nó cung cấp một bộ máy tìm kiếm dạng phân tán, có đầy đủ công ...
Kaopiz Software Co., Ltd. viết 9 tháng trước
5 0
Bài viết liên quan
White
0 0
Recap Ở phần trước em đã giới thiệu cho mọi người sơ qua về Steering Behaviors bao gồm khái niệm, phân loại cũng như viết về 2 loại Behaviors phổ b...
Kaopiz Software Co., Ltd. viết 10 tháng trước
0 0
White
0 1
Quản lý bộ nhớ trong unity Để hiểu về garbage collection hoặt động và xảy ra thế nào , trước hết chúng ta cần tìm hiểu về quản lý bộ nhớ trong unit...
Kaopiz Software Co., Ltd. viết 9 tháng trước
0 1
White
1 1
Lời nói đầu Sau một tháng ngồi quan sát những bài viết đã có ở trên Kipalog. Em quyết định viết một bài nhỏ chia sẻ về một trong những kỹ thuật xây...
Kaopiz Software Co., Ltd. viết 10 tháng trước
1 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
27 bài viết.
24 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!