12/08/2018, 10:26

Cơ bản về engine vật lý trong Unity

Nếu nói đến game không thể không nói đến tương tác vật lý tồn tại tại đa số game, tương tác vật lý áp dụng các luật vật lý khiến game có độ thực tế cao hơn. Mục đích của tương tác vật lý là sử dung thiết bị vi tính đẻ tái hiện lại những hiện tượng vật lý qua các công thức, tại thời điểm hiện tại ...

Nếu nói đến game không thể không nói đến tương tác vật lý tồn tại tại đa số game, tương tác vật lý áp dụng các luật vật lý khiến game có độ thực tế cao hơn. Mục đích của tương tác vật lý là sử dung thiết bị vi tính đẻ tái hiện lại những hiện tượng vật lý qua các công thức, tại thời điểm hiện tại máy tính cũng như đa số thiết bị điện tử đều có phần cứng khá tốt để tạo các tương tác gần giống tương đương với thế giới thực.

Với game hiện tại, đa số game studio sử dụng những engine vật lý từ phía thứ ba để phát triển game của mình, những engine phổ biến nhất hay được dung như Box2D (tồn tại trên nhiều ngôn ngữ và hệ máy, miễn phí, Angry Birds dung engine này), PhysX (engine của Nvidia, dung bởi nhiều game hành động như Batman, Assassin’s Creed), Havok (engine vật lý rất mạnh dung trong rất nhiều game cần tính toán độ va chạm chân thực nhất như Soul Calibur, Mortal Kombat, Tekken hay Skyrim) . Bài viết này nhằm mục đích giải thích và nêu ra những điều cần biết về tương tác vật lý trong game mà không đi quá sâu vào kỹ thuật, bài viết sẽ dung engine game Unity 3D để đưa ra những ví dụ cụ thể hơn, Unity 3D có engine vật lý là PhysX của NVidia(Unity 5 sử dụng PhysX ver.3).

Giới thiệu Rigidbody

Về cơ bản thì tương tác vật lý chia ra làm hai phần, mô phỏng rigid-body (vật cứng) và soft-body (vật mềm), tại đây chúng ta sẽ tập trung vào rigidbody. Trong mô phỏng rigid body các object được nhóm ra thành các loại khác nhau dựa trên chúng phải tương tác với nhau thế nào, thường thì loại mô phỏng này tốn ít tài nguyên hơn.

Rigid Body là hiệu ứng được mô phỏng nhiều nhất trong game, vì đa số vật mà chúng ta tương tác ngòai đời cũng tương đối cứng, và mô phỏng chúng tương đối đơn giản. Thông thường các tính toán vật lý đươc thực hiện bởi các engine vât lý, nó sẽ nhận được thông số tại mỗi thời điểm tương tác cộng thêm những thông số được người phát triển đưa vào trước, sau đó sự mô phỏng sẽ đươc thực hiện theo các bước, mỗi bước đẩy tiến độ của sự mô phỏng, chỉ vài khắc trong giây, và kết quả sẽ được thẻ hiện trên màn hình. Dĩ nhiên, công việc của engine chỉ là thực hiện các phép tính, còn các bước thế nào thường dựa vào sự cần thiết của từng game.

1 chút kiến thực vật lý. sự chuyển động của rigid body có thể được thể hiện bởi cơ học Newton, được sang lập dựa trên 3 điểu luật nổi tiếng của Isaac Newton:

  • Quán tính (Inertia) – Nếu không có lực (force) tác động lên vập, vận tốc (velocity) sẽ không thay đổi.
  • Lực, khối lượng và gia tốc – Lực được thực hiện trên vận tương đương với khối lượng (mass) nhân với gia tốc (acceleration). Với biểu thức là F = m*a.
  • Hành động và phản ứng – Với mỗi hành động sẽ có phản ứng tương tự, nói cách khác, mỗi khi một vật tạo ra lực trên vật khác, vật thứ hai này sẽ chịu lực tương tự với chiều hướng ngược lại so với cái thứ nhất. Với ba định luật đó, chúng ta có thể tạo một tương tác vật lý đơn giản mà chúng ta thường biêt ngoài đời, sau đây là biểu đổ thể hiện:

Loop.png

Rigidbody

Rigidbody là bộ phận quan trọng nhất trong engine vật lý, mỗi object đều tạo ra bởi Unity đểu được mặc định gắn componenet Rigidbody, nếu tạo ra object rỗng để đưa rigidbody vào object trong Unity chỉ cần chọn object mình muốn, chọn Components, Physics và Rigidbody. Khi áp dụng rigidbody lên bất kì vật nào, vật đó sẽ tự động có những tương tác vật lý mà không cần dòng code nào cả, rigid body sẽ được kéo xuống bởi trọng lực và sẽ va chạm với các vật chạm vào nó nếu component Collider tồn tại với cả 2 object. RigidBody có những thuộc tính sau đây:

  • Mass – Khối lượng của vật, không nên đặt chỉ số này cao hơn hoặc thấp hơn 100 lần so với các rigidbody khác.
  • Drag – Sức cản không khí sẽ ảnh hưởng đến object thế nào, 0 nghĩa là hoàn toàn không có sức cản, vô tận sẽ khiến cho object ngừng di chuyển.
  • Angular Drag – Sức cản không khỉ khi vật quay, lưu ý là không thể khiến object ngừng quay với angular drag vô tận.
  • Use Gravity – Nếu check, trọng lực sẽ được áp dụng lên object.
  • Is Kinematic – Nếu check, object sẽ không được điều khiển bởi engine vật lý mà chỉ có thể điều khiển bởi transform.
  • Interpolate – Dùng để điều chỉnh sự va chạm, độ va chạm có thể nhạy hơn tùy từng trường hợp.
  • Collision Detection – Dùng để ngăn chặn các object di chuyển quá nhanh xuyên qua các object khác mà không bị va chạm, như khi viên đạn di chuyển nhanh quá, và vượt qua object khác trước khi va chạm được update.
  • Ngoài ra RigidBody có thể được áp dụng lực trong code với function AddForce()

Unity-Rigidbody.png

Colliders

Colliders là vật mà engine vật lý sẽ dung để có thể nhận ra sự va chạm, không giống như các mesh, chúng nhận biết được mỗi khi va chạm với nhau. Đa số collider có hình dạng đơn giản nhằm mục đích tính toán đơn giản và dễ dàng hơn, phần lớn các object trong Unity sẽ được gắn collider mỗi khi tạo ra, với Cube là Box Collider, Sphere là Sphere Collider, Cylinder là Capsule Collider.

Unity-Box-Collider.png

Unity cung cấp những API sau đâu để phát hiện sự va chạm của các collider.

  • void OnCollisionEnter(Collision collision) – Chạy 1 lần tại thời điểm va chạm giữa 2 vật.
  • void OnCollisionStay(Collision collision) – Chạy trong mỗi khung hình tại thời điểm 2 vật còn chạm vào nhau.
  • void OnCollisionExit(Collision collision) – Chạy tại khung hình cuối cùng khi 2 vật không còn chạm vào nhau nữa. Với class Collision chúng ta có thể lấy ra những thuộc tính như:
  • Contacts – điểm va chạm giữa 2 vât, tính bằng vector3.
  • GameObject – game object va chạm với object gốc.
  • RelativeVelocity – vận tốc tương đối.

1 ví dụ đơn giản để áp dụng những thông tin được API của Unity cung cấp, khi Assassin Ezio Auditore Firenze rơi từ trên độ cao xuống dưới mặt đất, số lượng sát thương sẽ được áp dụng vào nhân vật Assassin:

void OnCollisionEnter(Collision collision) {
        if (collision.relativeVelocity.magnitude < 10) {     //Áp dụng sát thương nếu vận tốc thấp.
            Ezio.ApplyDamage(collision.relativeVelocity.magnitude * damagePerVelocity);
            return;
        }
        if (collision.relativeVelocity.magnitude >= 10) {    //Thật đáng tiếc
            Ezio.Kill();
            return;
         }
    }

Colliders với thuộc tính As Trigger

Để có thể dung Trigger trong collider, đơn giản chỉ cần tick vào checkbox As Trigger trong Componenet Collider ở Inspecter. Trong trạng thái này collider sẽ không bị va chạm bởi bất kỳ object nào, nhưng bản thân sẽ được dùng để phát hiện những va chạm trên nó, tạo ra những event có thể điều khiển được trong code với những function sau đây:

  • void OnTriggerEnter(Collider other) – Chạy 1 lần tại thời điểm va chạm giữa 2 vật.
  • void OnTriggerStay(Collider other) – Chạy trong mỗi khung hình tại thời điểm 2 vật còn chạm vào nhau.
  • void OnTriggerExit(Collider other) – Chạy tại khung hình cuối cùng khi 2 vật không còn chạm vào nhau nữa.

Các class này sẽ đươc gọi ra khi một Collider khác va chạm vào Collider có thuộc tính As Trigger, từ Collider có thể lấy ra thông tin về object bị va chạm, cụ thể có thể dùng nó để kiểm tra sự va chạm vào 1 vật mà không áp dụng lại lực tương đương, như ví dụ Mario mỗi khi chạm vào đồng tiền:

void OnTriggerEnter(Collider other) {
    if (other.name == “Mario”) {   //Nếu vật va chạm có tên Mario
        GameController.AddCoin();  //Tính coin cho người chơi
        Destroy(this.gameObject);  //Phá hủy object này
    }
}

To be continue - Advanced

Đây là những bộ phận cơ bản cần phải biết khi làm việc với engine vật lý trong Unity, dĩ nhiên với PhysX, việc điều khiển vật lý còn nhiều bộ phận phức tạp, đòi hỏi với những game cần độ tương tác vật lý cao, cũng như chuẩn xác, vơi nhiều object có hình dạng và cử động phức tạp, những điều này sẽ được nói ra trong phần nâng cao của tương tác vật lý trong engine vật lý của Unity.

0