Công cụ Occlusion Culling trong Unity

Một phần của tài liệu Tổng quan về Unity Engine (Trang 59)

Để sử dụng Occlusion Culling, chúng ta cần phải thực hiện một số thao tác cài đặt. Đầu tiên, màn chơi của chúng ta cần phải được chia nhỏ thành từng mảnh với kích thước hợp lý. Tiếp theo, đánh dấu (tag) các đối tượng mà chúng ta muốn chúng trở thành một phần dữ liệu trong quá trình thực hiện kỹ thuật Occlusion Culling.

Hình 8.3. Đánh dấu đối tượng.

Sau khi thực hiện các thao tác cài đặt cơ bản, chúng ta đã có thể sử dụng công cụ Occlusion Culling với các thẻ chứ năng mà Unity cung cấp để Unity tính toán và thu thập dữ liệu cho tối ưu hóa.

Hình 8.4. Thẻ Object trong công cụ Occlusion

Trang 61 CHƯƠNG 8. TỐI ƯU HÓA ĐỒ HỌA

Hình 8.6. Thẻ Visualization trong công cụ Occlusion

Các thẻ Object, Bake, Visualization cung cấp chức năng cho phép chúng ta xác định vùng, các đối tương sẽ áp dụng Occlusion; xác định Camera cần dùng dữ liệu từ Occlusion Culling để xử lí, kết xuất hình ảnh. Cho phép chúng ta tùy chọn về các giới hạn xa, gần, kích thước của các ô chứa đối tượng Occlusion.

CHƯƠNG 9. CĂN BN V LP TRÌNH TRÊN UNITY 9.1. GII THIU

Engine Unity hỗ trợ các ngôn ngữ C#, Javascript, Boo mỗi ngôn ngữ có ưu, nhược điểm khác nhau tại một hoàn cảnh nhất định. Các đoạn code được viết bằng C# sẽ được thực thi nhanh hơn, sử dụng C# là một trong các biện pháp tối ưu hóa cho Unity Game. Bên cạnh đó, Javascript lại có điểm mạnh về mặt “thoáng” khi trao đổi dữ liệu giữa các Component, một số phương thức được dễ dàng sử dụng bởi Javascript do không cần xác định chính xác kiểu của biến. Các Component khác nhau được viết bằng các ngôn ngữ khác nhau vẫn có thể trao đổi thông tin và được truy cập bình thường, điều này có nghĩa là developer được thoải mái trong việc chọn ngôn ngữđể giải quyết vấn đề.

Hình 9.1. Giao diện viết code của Unity.

9.2. LP COMPONENTS

Là lớp cơ bản nhất được tích hợp vào các GameObject (danh từ chỉ các đối tượng trong game), lớp Component bao gồm các thuộc tính lưu trữ những thông tin cơ

Trang 63 CHƯƠNG 9. CĂN BẢN VỀ LẬP TRÌNH TRÊN UNITY

bản và quan trọng nhất đối với một GameObject như vị trí của đối tượng trong không gian 3D, độ xoay của đối tượng, tên, tag …v…v

Thuc tính Chú thích

transform Thông tin về vị trí, độ xoay.

rigidbody Giả lập khối lượng và trọng lượng cho GameObject.

camera Truy xuất đến các thuộc tính của class Camera nếu GameObject được tích hợp một camera.

light đượTruy xuc tích hất đếợp mn các thuột Light.ộc tính của class Light nếu GameObject animation Truy xuGameObject bao gất đến các thuồm các animation.ộc tính của class Animation nếu

constantForce Truy xuGameObject ất đến các thuộc tính của class ConstantForce nếu được tích hợp ConstantForce.

renderer Truy xuđược tích hất đếợp Renderer.n các thuộc tính của class Renderer nếu GameObject audio Truy xuất đến các thuộc tính của class Audio nếu GameObject

được tích hợp Audio.

guiText Truy xuđược tích hất đếợp GUIText.n các thuộc tính của class GUIText nếu GameObject networkView Truy xuất đến các thuộc tính của class NetworkView nếu

GameObject được tích hợp NetworkView. guiTexture Truy xu

ất đến các thuộc tính của class GUITexture nếu GameObject được tích hợp GUITexture.

collider Truy xu

ất đến các thuộc tính của class Collider nếu GameObject được tích hợp Collider (được dung để kiễm tra các va chạm ). hingeJoint Truy xuGameObject ất đến các thuộc tính của class HingeJoint nếu

được tích hợp HingeJoint.

particleEmitter GameObject Truy xuất đến các thuđược tích hộc tính cợp ParticleEmitter.ủa class ParticleEmitter nếu particleSystem Truy xuất đến các thuộc tính của class ParticleSystem nếu

GameObject được tích hợp ParticleSystem. gameObject Truy xuất đến đối tượng mà nó tích hợp đến.

tag Tag của component.

Chú ý: Mặc định khi khởi tạo một đối tượng, đối tượng đó sẽ mang tên “GameObject” và được tích hợp sẵn thành phần Transform.

Hình 9.2. Một GameObject mới khởi tạo.

Phương thc Chú thích

GetComponent Trả về kiểu Component được tích hợp vào đối tượng. GetComponentInChildren hoTrảặ vc con cề kiểu Component ủa đối tượng.được tích hợp vào đối tượng, GetComponentsInChildren GiComponent.ống GetComponentsInChildren nhưng trả về nhiều GetComponents Giống GetComponent nhưng trả về nhiều Component

CompareTag Đối tượng có thuộc tag nào không? SendMessageUpwards

Gữi yêu cầu thực hiện một phương thức đến các thành phần được tích hợp trong cùng một đối tượng.

SendMessage Gphữầi yêu cn được tích hầu thực hiợp trong cùng mện một phương thột đốứi tc ượđến các thành ng. BroadcastMessage Gt ữi yêu cầu thực hiện một phương thức đến các đối

ượng con.

9.3. TRUY XUT ĐẾN THUC TÍNH CA SCRIPT

Bắt đầu bằng một ví dụ cơ bản, đoạn code sau sẽ di chuyển một đối tượng thông qua input và một biến hiệu chỉnh tốc độ.

Trang 65 CHƯƠNG 9. CĂN BẢN VỀ LẬP TRÌNH TRÊN UNITY

Hình 9.3. Một GameObject đã gắn Script.

Chú ý: Sau khi tích hợp script trên vào một đối tượng, thuộc tính speed của class Move được public ra ngoài để ta có thể hiệu chỉnh trực tiếp bằng cách click chuột và nhập thông số, bản thân các script nên được xây dựng như một tool để tiện lợi cho việc hiệu chỉnh và tránh can thiệp vào mã nguồn, ngoài ra còn đơn giản hóa việc sử dụng script.

Trong quá trình phát triển chúng ta sẽ có nhu cầu về việc hiệu chỉnh tốc độ thông qua code, sử dụng phương thức GetComponent để truy xuất đến thuộc tính của một thành phần bất kỳđược tích hợp trong đối tượng.

Hình 9.4. GameObject tích hợp Scrip SetSpeed.

Gii thích: Sau khi tích hợp script SetSpeed vào cùng một đối tượng với script Move, thuộc tính gameObject sẽ truy xuất đến đối tượng chứa 2 script này và thông qua phương thức GetComponent để truy xuất đến một thành phần bất kỳđược tích hợp vào đối tượng, cụ thểởđây là script Move.

Chú ý: Tại script C# không thể truy xuất đến script Javascript thông qua phương thức GetComponent.

9.4. CÁC PHƯƠNG THC CƠ BN

Khi khởi tạo một script, mặc định nó đã chứa các phương thức Start(), Update(), đây là hai phương thức rất hữu dụng, ngoài ra còn một số phương thức khác được liệt kê dưới đây:

- Update(): Những đoạn code thuộc phương thức này sẽ được gọi lại mỗi frame (khung hình).

- FixedUpdate(): Giống với Update nhưng ta có thể hiệu chỉnh được số khung hình ban đầu, và không bị ảnh hưỡng khi tần số frame không ổn định.

Trang 67 CHƯƠNG 9. CĂN BẢN VỀ LẬP TRÌNH TRÊN UNITY

- Awake(): Những đoạn code thuộc phương thức này được gọi khi script ở giai đoạn khởi tạo, thường được dùng để thiết lập hoặc tải dữ liệu ban đầu cho các Component.

- Start(): Được gọi thực hiện trước phương thức Update() nhưng lại sau Awake(), Khác nhau cơ bản giữa Start() và Awake() là phương thức Start() chỉđược gọi khi script không bịđình chỉ hoạt động (enabled).

- OnCollisionEnter(): Những đoạn code thuộc phương thức này sẽđược thực thi khi đối tượng chứa nó bao gồm một Collider và va chạm với một Collider hoặc Rigidbody của một đối tượng khác.

- OnMouseDown(): Những đoạn code thuộc phương thức này sẽ được thực thi khi chuột của người chơi click vào một đối tượng có tích hợp thành phần GUIElement hoặc Collider.

9.5. DEBUGGING

Unity cung cấp lớp Debug để hỗ trợ lập trình viên theo dõi và kiểm soát các lỗi, ởđây chúng ta quan tâm đến phương thức Debug.Log().

Phương thức Log() cho phép người dùng gửi một thông tin đến Unity Console nhằm mục đích:

- Chứng minh rằng đoạn mã này đang được thực hiện. - Báo cáo tình trạng hiện tại của biến.

Trở lại ví dụ về lớp SetSpeed, kiễm tra tốc độ của đối tượng mỗi khi người chơi tăng tốc.

Kết quả:

Hình 9.5. Cửa số Debug và các thông tin Debug.

9.6. TI ƯU HÓA MÃ NGUN 9.6.1. S dng biến tĩnh 9.6.1. S dng biến tĩnh

Đối với ngôn ngữ Javascript, chúng ta cần phải xác định rõ kiểu của biến đang sử dụng để hệ thống không phải tốn nhiều thời gian xử lý.

Trang 69 CHƯƠNG 9. CĂN BẢN VỀ LẬP TRÌNH TRÊN UNITY

Với đoạn mã trên biến foo là loại biến động, việc gọi phương thức DoSomeThing() sẽ tốn nhiều thời gian do kiểu của biến chưa được xác định và hệ thống Unity sẽ làm thay chúng ta điều đó.

Với đoạn mã đã được sửa như trên, xác định chính xác kiểu của biến là một trong những cách tốt nhất để tối ưu hóa cho ngôn ngữ Javascript.

Chú ý: Để chắc rằng chúng ta không sử dụng bất kỳ một biến động nào, sử dụng từ khóa “#pragma strict”, hệ thống Unity sẽ tự động báo lỗi nếu trong script tồn tại bất kỳ biến nào không có kiểu xác định. Vì vậy sử dụng ngôn ngữ C# cũng là một trong những cách tối ưu hóa hữu hiệu.

9.6.2. S dng các thành phn ca GameObject thông qua biến tĩnh

Nhưđã tìm hiểu ở các mục trên, bản thân một GameObject luôn được tích hợp sẵn các thành phần để lưu trữ thông tin của chúng trong không gian 3D, ở đây chúng ta sẽ lấy ví dụ cụ thể với thành phần transform.

Mỗi khi chúng ta gọi một thành phần bất kỳ của GameObject, hệ thống Unity sẽ tốn thời gian để duyệt qua các thành phần được tích hợp trong GameObject để cuối cùng trả về kết quả thích hợp, để tiết kiệm khoản thời gian đó nên sử dụng thành phần của GameObject thông qua biến tĩnh. Đoạn mã trên được sửa lại như sau:

Chú ý: Tuy thời gian để hệ thống truy xuất đến các thành phần là không nhiều, nhưng với một số lượng lớn code thì chúng ta sẽ tiết kiệm được một khoản thời gian lớn, vì vậy đây cũng là một cách tối ưu hóa hữu hiệu.

9.6.3. S dng mng tĩnh

Các lớp ArrayList hay Array thì rất dễ sử dụng, chúng ta có thể dễ dàng thêm một phần tử vào mảng và sử dụng các phương thức, nhưng chi phí phải trảđể hệ thống thực hiện điều đó là rất cao. Thay vì vậy, việc sử dụng các mảng được cấu trúc sẵn sẽ giảm bớt công việc cho hệ thống, vì các phần tử trong mảng có cùng kiểu và độ dài của mảng đã được xác định từ trước, chúng ta chỉ mất thời gian để xác định độ dài mảng cần thiết, bù lại chúng ta tiết kiệm được một khoản chi phí khá lớn.

Ví dụ:

Chú ý: Hạn chế sử dụng for, foreach, nên sử dụng while để đạt được tốc độ tối ưu.

Trang 71 CHƯƠNG 9. CĂN BẢN VỀ LẬP TRÌNH TRÊN UNITY

9.6.4. Hiu chnh tn s s dng phương thc

Đặt vn đề: Khi người chơi ở quá xa, kẻđịch sẽở trạng thái ngủ tạm thời.

Code x lý:

Gii thích: Đoạn mã trên sẽ xét khoảng cách giữa người chơi và kẻđịch tại mỗi frame, nhưng điều đó là không cần thiết, trung bình một giây hệ thống chạy từ 30 đến 40 khung hình, chi phí bỏ ra quá lớn nhưng hiệu quả lại không cao.

9.6.5. Yield và Coroutine

Các Coroutine cho phép chúng ta đình trệ hay làm trễ việc thực thi một đoạn mã hoặc một phương thức, áp dụng để xử lý vấn đề nêu trên.

Gii thích: Việc thực thi vòng lập while sẽ bị chậm lại 2 giây sau mỗi lần lặp do tác động của yield, việc xét khoảng cách giữa người chơi và kẻđịch sẽđược thực thi 2 giây 1 lần, tiết kiệm được nhiều chi phí và giảm nhẹ công việc cho hệ thống.

Chú ý: Đối với C#, phương thức sử dụng yield phải thuộc kiểu IEnumerator, riêng với Javascript thì không, ví dụ minh họa:

Trang 73 CHƯƠNG 10. LẬP TRÌNH GIẢI QUYẾT CÁC VẤN ĐỀ TRONG GAME FPS

CHƯƠNG 10. LP TRÌNH GII QUYT CÁC VN ĐỀ

TRONG GAME FPS

10.1. MÔ PHNG NHÂN VT DƯỚI GÓC NHÌN TH NHT 10.1.1. First Person Controller Prefab 10.1.1. First Person Controller Prefab

Thể loại game FPS là rất phổ biến hiện nay, vì vậy hầu hết các game engine đều có các gói tài nguyên hỗ trợ developer giả lập “trạng thái người chơi”, ở đây chúng ta chú ý đến đối tượng First Person Controller.

10.1.2. Phân tích cu trúc FPC

First Person Controller(FPC) là một đối tượng đã được Unity đóng gói sẵn các script và các Component khác để hổ trợ developer, cơ bản cấu tạo của FPC gồm 3 phần chính: First Person Controller, Graphics và Main Camera.

a. Đối tượng 1: First Person Controller

Là cha của cả nhóm đối tượng, được tích hợp các script quan trọng để xử lý các vấn đề cơ bản của game PFS như di chuyển, ngồi xuống, nhảy, xoay camera …v…v.

Hình 10.1. First Person Controller.

- Thành phn FPSWalker (Script): Được viết bằng Javascript, cho phép người chơi di chuyển thông qua input, có các biến được public ra bên ngoài như Speed, Jump Speed, Gravity để thuận tiện cho việc tùy chỉnh từ bên ngoài.

- Thành phn Character Controller: Là một mạng lưới bao phủ lên đối tượng, có nhiệm vụ kiễm tra các tương tác vật lý và hỗ trợ di chuyển cho đối tượng trong không gian 3D, bao gồm các thuộc tính sau:

Trang 75 CHƯƠNG 10. LẬP TRÌNH GIẢI QUYẾT CÁC VẤN ĐỀ TRONG GAME FPS

Hình 10.2. Character Controller. • Height: Độ cao của mạng lưới bao quanh đối tượng. • Radius: Độ rộng của mạng lưới bao quanh đối tượng.

Slope Limit: Độ dốc giới hạn của địa hình mà đối tượng có thể tiếp tục di chuyển được.

Step Offset: Giống như khi đang đi lên một cầu thang, đây là thông số về độ cao giới hạn của bậc thang mà đối tượng có thể bước lên.

Skin Width: Khi đối tượng đột ngột va chạm với một đối tượng khác ở tốc độ cao, hay bị kẹt trong một bức tường, dựa vào thông số này hệ thống sẽ ngừng việc kiểm tra va chạm. Nên để thông số này bằng 10% bán kính nhân vật.

Min Move Distance: Input còn phụ thuộc vào độ nhạy của bàn phím hay con chuột của người chơi, vì vậy đây là giá trị di chuyển nhỏ nhất ứng với giá trị input nhỏ nhất.

Center: Tâm của mạng lưới bao quanh đối tượng.

- Thành phn Mouse Look (Script): Được viết bằng C#, là một hệ thống quản lý việc xoay của đối tượng quanh một trục cho trước.

Axes: Thuộc tính cho phép nhập các trục X, Y hoặc MouseX, MouseY để kiểm soát việc xoay của đối tượng.

Minimum X / Maximum X: Giá trị của thuộc tính này sẽ giới hạn độ xoay của đối tượng, mặc định là -360 đến 360 độ.

Minimum Y / Maximum Y: Tương tự như trên.

b. Đối tượng 2: Graphics

Đối với thể loại game FPS, người chơi không bao giờ nhìn thấy toàn bộ cơ thể của họ, đối tượng này giúp developer dễ dàng nhận biết nó trong thế giới 3D, ngoài ra đối tượng này còn là vị trí thích hợp để chứa các model của nhân vật, khi game được chạy, đối tượng này sẽđược tắt render để hiện lên các model của nhân vật.

Hình 10.3. Đối tượng Graphics.

Thành phn Mesh Filter và Mesh Renderer: Trong ví dụ trên thành phần mesh filter mang tên Poly Surface 2, bản thân nó là nơi chứa dữ liệu về các lưới đồ họa(mesh) của model, trên thực tế một model nhân vật hoàn chỉnh sẽ bao gồm nhiều bộ phận, mỗi bộ phận được lưu trữ trong một mesh filter và được vẽ nên bởi một mesh renderer. Ngoài việc quyết định một mesh filter có được vẽ lên hay không, mesh renderer còn thể hiện được chất liệu và đổ bóng.

10.1.3. Đối tượng 3: Main Camera

Trong FPC prefab, camera được đặt ở vị trí tương tự như tầm mắt của con người và bị điều khiển bởi script, cho phép người chơi nhìn xung quanh trong khi đang di chuyển hay đứng yên.

Trang 77 CHƯƠNG 10. LẬP TRÌNH GIẢI QUYẾT CÁC VẤN ĐỀ TRONG GAME FPS

- Thành phn Camera: Là thành phần chính tạo nên tầm nhìn của người chơi trong thế giới 3D.

Hình 10.4. Thành phần Camera.

- Clear Flags: Cho phép camera render các vật liệu chỉ định, ở đây mặc định là loại Skybox.

- Back Ground Color: Nếu thế giới 3D của chúng ta không có một bầu trời, thì sẽđược thay thế bằng màu của thuộc tính này.

Một phần của tài liệu Tổng quan về Unity Engine (Trang 59)