Tìm hiểu về Steering Behaviors (Phần 1) - Seek, Flee

7
Nguyễn Thanh Long viết gần 6 năm trước

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 dựng hành vi cho AI mà em sử dụng khá nhiều. Kỹ thuật này rất đơn giản những kết quả nó đem lại là vô cùng ảo diệu. Đó là kỹ thuật Steering Behaviors kỹ thuật giúp cho những con AI biết tổ lái.

Giới thiệu

Khái niệm

Steering Behaviors được tạo ra để giúp những con AI có hành vi di chuyển giống với thực tế bằng cách sử dụng cách tính toán lực Vector đơn giản. Kỹ thuật này không sử dụng những tính toán phức tạp với các tính toán bằng các biến Global mà làm việc dựa trên Local Information như là vị trí hay vận tốc hiện tại. Điều này khiến Steering Behaviors rất đơn giản để cài đặt nhưng vẫn đem lại sự ảo ma cho những con AI.
Thường thi Steering Behaviors được áp dụng trong việc xây dựng Heat Seeking Missle hay là những con Zombie mà không cần phải cài đặt Path Finding cồng kềnh.
Có thể kết hợp Path Finding với Steering Behavior để tạo ra một thứ còn hơn cả ảo diệu - Unity Navmesh Agent

Nguyên Lý

Em không có giỏi vật lý lắm nên mong là những lời giải thích sau sẽ đem lại cái gì đó chắc thế
alt text
Như đã trình bày Steering Behaviors là tính toán dựa trên Vector-Base.
Từng con AI sẽ có cái gọi là vị trí hiện tại và vector vận tốc. Vector vận tốc sẽ bao gồm hướng và con AI sẽ di chuyển và độ nhanh chậm của chúng alt text
Để tiến hành cài đặt cần có những quy tắc sau:

  • Không được thêm vào một Vector vận tốc chưa được normalize - Điều này đảm bảo Vector ta có được chỉ gồm hướng của Vector đó, độ lớn của Vector được đưa về 1 để có thể nhân với hệ số đặc biệt sau này.
  • Tốc độ không được lớn hơn tốc độ tối đa Max_Speed
  • Lực được tổng cộng không được lớn hơn lực tối đa Max_Force
  • Một Object sẽ luôn có một biến Velocity để lưu hướng và độ lớn vận tốc của vật

Để đảm bảo không được vượt quá các Parameter tối đa ta sẽ sử dụng hàm ClampMagnitude(value , max_value);
Về cơ bản một con AI được cài đặt Steering Behaviors sẽ gồm:
steeringForce = Vector2.zero;
steeringForce = steeringForce + TheForce
steeringForce = Vector2.ClampMagnitude(steeringForce, max_force);
steeringForce = steeringForce / mass;
velocity = Vector2.ClampMagnitude(velocity + steeringForce, max_speed);
transform.Translate(velocity * Time.deltaTime);

Trong đoạn code trên TheForce là lực được cộng thêm vào với steeringForce. steeringForce ở mỗi lần Update sẽ độ lớn và hướng tác động của lực tác động lên Object để di chuỷen chúng.

Phân loại

TheForce có các loại sau

  • Seek(Tìm kiếm)
  • Flee (Chạy trốn)
  • Arrival (Đáp tới how to dịch )
  • Wander (Lang thang)
  • Pursuit (Đuổi)
  • Evade (Né)
  • Collision Avoidance (Tránh vật cản)
  • Path Following (Đi theo đường có sẵn)
  • Leader Command (Những hành vi đối với lãnh đạo) Follow, Out of the way.
  • Cohesion (Ôm nhau)
  • Separation (Tránh xa nhau)
  • Queue (Hành vi xếp hàng của những người văn minh) Từng loại một sẽ có cái gọi là hệ số độ lớn sẽ nhân với Vector đã được normalize để đưa ra độ lớn cần thiết của lực cần tác động. Hệ số này càng lớn thì lực của từng loại sẽ càng có tác động mạnh hơn lên Object. #Chi tiết Để tiện cho việc xây dựng sau này mỗi một TheForce sẽ được viết dưới dạng một method có giá trị trả ra là 1 vector

Seek

Seek là hành vi một Object sẽ luôn theo đuổi một Target của nó. Ở trong Unity đã có sẵn một hàm MoveToward, tuy nhiên hàm này khiến cho con AI luôn luôn đuổi theo mục tiêu của nó. Điều này sẽ khiến cho người chơi phải liên tục di chuyển.

alt text

Còn Seek? Xem gif sau sẽ rõ :insert dejavu meme:

alt text

Nhìn khác bọt hẳn luông. Seek sẽ giúp người chơi có khoảng thời gian nghỉ giữa những lần input di chuyển qua đó có những khoảng nhỏ thời gian cho các công việc phán đoán khác.

Vậy bắt đầu tiến hành cài đặt thôi!

Để xây dựng được hàm Seek() ta sẽ cần một Vector chỉ hướng giữa mục tiêu và bản thân của Seeker - AI biết Seek ?? :D ??. Để có được đơn giản ta sẽ tìm khoảng cách tương đối giữa mục tiêu và Object bằng cách lấy hiệu toạ độ của chúng.
Như vậy hàm Seek() sẽ như sau:
Seek(target)
{
Vector2 desired_velocity = (target - transform.position).normalized *Seek_Coffiency;
Vector2 seek = desired_velocity - velocity;
return seek;
}

desired_velocity chính là vận tốc mà chúng ta muốn đưa vào Object, vận tốc này sẽ bao gồm hướng và độ lớn cần thiết để thêm vào.
Seek_Coffiency chính là hệ số của Seek.
Sau đó tính toán vận tốc cần có và trừ đi vận tốc hiện tại để có thể đưa ra đúng lực mà ta cần. Sau khi trả ra được lực cần thiết ta thêm lực này vào trong steeringForce tại Update() :
steeringForce = steeringForce + Seek(Target)
Vào lúc này con AI đã biết tăng tốc, đánh võng, úp vỉa các kiểu để có thể tìm đến mục tiêu của chúng rồi.

Flee

Flee là một hành vi là con AI sẽ chạy trốn khỏi Target nào đó, thường thì khi tích hợp hành vi này sẽ bao gồm cả phạm vi phát hiện nguy hiểm (Danger Zone) nhưng để đơn giản trước tiên hãy xây dựng hàm Flee(target) đã.
Về cơ bản Flee cũng sử dụng khoảng cách tương đối giữa Object và target để đưa ra được lực tác động phù hợp. Nói thì có vể hoa mỹ những thật ra Flee = Seek * -1. Hàm Flee(target) được xây dựng như sau:
Flee(target)
{
Vector2 desired_velocity = (target - transform.position).normalized *Flee_Coffiency;
Vector2 flee = -desired_velocity - velocity;
return flee;
}

Chú ý vào flee = -desired_velocity - velocity, chắc tại đâu không cần giải thích thêm đâu ha :D.
Tương tự như Seek ta sẽ thêm kết quả vào steeringForce để tạo ra 1 con AI chỉ biết chạy (-_-!).

alt text

Kết luận

Một con AI chỉ biết đuổi hay chỉ biết chạy sẽ là một con AI khá là ngu. Tuy nhiên vì kỹ thuật này sử dụng toán Vector là chính nên việc cộng các Vector này để đưa ra một lực tổng hợp rất là dễ. Đơn giản ta sẽ thêm vào steeringForce cả 2 lực:
steeringForce = steeringForce + seek(target) + Flee(target).
Object sử dụng cái này sẽ có thể vừa đuổi theo vừa chạy trốn, khá tuyệt phải không? Và chính các hệ số như Seek_Coffiency hay Flee_Coffiency quyết định xem Object sẽ ưu tiên cái gì? Được ăn hay bị ăn?
Tính chất này cũng sẽ được áp dụng cho các loại Steering Behaviors khác sau này. Và tính chất này cũng là tính chất giúp cho AI có được những hành vi di chuyển phức tạp khi được cài đặt những hành vi phù hợp
Ở bài viết sau sẽ là nội dung của Arrival - Khi Seek chưa hay cho lắm. Và Evade - Tránh né đẹp trai :D

Tài liệu tham khảo

https://gamedevelopment.tutsplus.com/series/understanding-steering-behaviors--gamedev-12732

Bình luận


White
{{ comment.user.name }}
Hay Bỏ hay
{{ comment.like_count}}
White

Nguyễn Thanh Long

12 bài viết.
0 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}

  Cùng một tác giả


{{like_count}}

kipalog

{{ comment_count }}

Bình luận


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

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

 Cùng một tác giả