Hero image

Hiệu năng vật lý được nâng cao mang lại trải nghiệm chơi game mượt mà hơn.

Trang web này đã được dịch bằng máy để thuận tiện cho bạn. Chúng tôi không thể đảm bảo tính chính xác hoặc độ tin cậy của nội dung được dịch. Nếu bạn có thắc mắc về tính chính xác của nội dung được dịch, vui lòng tham khảo phiên bản tiếng Anh chính thức của trang web.

Đây là bài viết thứ năm trong loạt bài hướng dẫn tối ưu hóa các dự án Unity của bạn. Hãy sử dụng chúng như một hướng dẫn để chạy ở tốc độ khung hình cao hơn với ít tài nguyên hơn. Sau khi đã thử áp dụng những phương pháp tốt nhất này, hãy nhớ xem thêm các trang khác trong loạt bài này:

Vật lý có thể tạo lối chơi phức tạp, nhưng điều này cũng làm giảm hiệu năng. Khi đã nắm rõ các chi phí này, bạn có thể điều chỉnh mô phỏng để quản lý chúng một cách phù hợp. Hãy sử dụng những mẹo này để duy trì tốc độ khung hình mục tiêu và tạo trải nghiệm phát lại mượt mà với hệ thống Vật lý tích hợp sẵn của Unity (NVIDIA PhysX).

Xem các hướng dẫn tối ưu hóa mới nhất của chúng tôi dành cho nhà phát triển và nghệ sĩ Unity 6:

Kiểm tra các bộ va chạm của bạn

Các lưới được sử dụng trong vật lý trải qua một quá trình gọi là "nấu". Bước này chuẩn bị lưới để nó có thể hoạt động với các truy vấn vật lý như chiếu tia, tiếp xúc, v.v.

MeshCollider có một số CookingOptions giúp bạn kiểm tra tính hợp lệ của lưới cho các thao tác vật lý. Nếu bạn chắc chắn rằng lưới của mình không cần các bước kiểm tra này, bạn có thể tắt chúng để tăng tốc thời gian nấu.

Trong phần CookingOptions cho mỗi MeshCollider, chỉ cần bỏ chọn EnableMeshCleaning, WeldColocatedVertices và CookForFasterSimulation. Các tùy chọn này rất hữu ích cho các mô hình lưới được tạo ra theo quy trình trong quá trình chạy, nhưng có thể bị vô hiệu hóa nếu mô hình lưới của bạn đã có đủ các tam giác cần thiết.

Ngoài ra, nếu bạn đang nhắm mục tiêu vào PC, hãy đảm bảo rằng bạn luôn bật tùy chọn "Use Fast Midphase". Quá trình này chuyển sang thuật toán nhanh hơn từ PhysX 4.1 trong giai đoạn giữa của mô phỏng (giúp thu hẹp một tập hợp nhỏ các tam giác có khả năng giao nhau để truy vấn vật lý).

Tìm hiểu thêm trong tài liệu CookingOptions .

Giao diện Tùy chọn nấu ăn trong trình chỉnh sửa Unity

Các lựa chọn nấu nướng cho lưới

Sử dụng Physics.BakeMesh

Nếu bạn tạo lưới mô hình theo quy trình trong quá trình chơi game, bạn có thể tạo Mesh Collider trong thời gian chạy. Tuy nhiên, việc thêm trực tiếp thành phần MeshCollider vào lưới sẽ xử lý/thực thi các phép toán vật lý trên luồng chính. Việc này có thể tiêu tốn đáng kể thời gian xử lý của CPU.

Sử dụng Physics.BakeMesh để chuẩn bị lưới cho việc sử dụng với MeshCollider và lưu dữ liệu đã được xử lý cùng với chính lưới đó. Một MeshCollider mới tham chiếu đến lưới này sẽ sử dụng lại dữ liệu đã được tạo sẵn (thay vì tạo lại lưới). Điều này có thể giúp giảm thời gian tải Scene hoặc thời gian khởi tạo đối tượng sau này.

Để tối ưu hóa hiệu năng, bạn có thể chuyển việc xử lý lưới sang một luồng khác bằng hệ thống tác vụ C# .

Hãy tham khảo ví dụ này để biết chi tiết về cách xử lý lưới trên nhiều luồng.

Giao diện BakeMeshJob

BakeMeshJob trong Profiler

Điều chỉnh cài đặt của bạn

Trong phần Cài đặt người chơi , hãy chọn tùy chọn "Prebake Collision Meshes" bất cứ khi nào có thể. Chúng tôi cũng khuyến nghị nên xem lại thiết lập Ma trận va chạm để đảm bảo rằng các đối tượng người chơi và cơ chế trò chơi nằm ở đúng lớp.

Loại bỏ lệnh gọi lại từ các trình kích hoạt cho các lớp không cần thiết có thể mang lại lợi ích lớn, vì vậy hãy cố gắng đơn giản hóa Ma trận va chạm lớp của bạn. Bạn có thể chỉnh sửa Cài đặt Vật lý thông qua Cài đặt Dự án > Vật lý .

Tìm hiểu thêm trong tài liệu về Ma trận va chạm .

Giao diện cài đặt dự án Vật lý

Điều chỉnh cài đặt dự án vật lý để tối ưu hóa hiệu năng.

Điều chỉnh tần số mô phỏng

Các công cụ vật lý hoạt động bằng cách chạy trên một bước thời gian cố định. Để xem mức chi phí cố định mà dự án của bạn đang chạy, hãy vào Chỉnh sửa > Cài đặt dự án > Thời gian .

Trường Fixed Timestep xác định độ chênh lệch thời gian được sử dụng bởi mỗi bước vật lý. Ví dụ, giá trị mặc định là 0,02 giây (20 ms) tương đương với 50 khung hình/giây, hay 50 Hz.

Vì mỗi khung hình trong Unity mất một khoảng thời gian thay đổi, nên nó không hoàn toàn đồng bộ với mô phỏng vật lý. Bộ máy sẽ đếm ngược đến bước thời gian vật lý tiếp theo. Nếu một khung hình chạy chậm hơn hoặc nhanh hơn một chút, Unity sẽ sử dụng thời gian đã trôi qua để biết khi nào cần chạy mô phỏng vật lý ở bước thời gian thích hợp.

Trong trường hợp việc chuẩn bị khung hình mất nhiều thời gian, điều này có thể dẫn đến các vấn đề về hiệu suất. Ví dụ, nếu trò chơi của bạn gặp phải hiện tượng tăng đột biến tải (ví dụ: tạo nhiều GameObjects hoặc tải tập tin từ ổ đĩa), thì quá trình xử lý khung hình có thể mất 40 ms hoặc hơn. Với bước thời gian cố định mặc định là 20 ms, điều này sẽ khiến hai mô phỏng vật lý chạy trên khung hình tiếp theo để "bắt kịp" với bước thời gian thay đổi.

Việc bổ sung thêm các mô phỏng vật lý sẽ làm tăng thêm thời gian xử lý khung hình. Trên các nền tảng cấp thấp hơn, điều này có thể dẫn đến sự suy giảm hiệu năng nghiêm trọng.

Việc mất nhiều thời gian hơn để chuẩn bị khung hình tiếp theo cũng làm tăng thêm lượng dữ liệu cần xử lý cho các mô phỏng vật lý. Điều này dẫn đến tốc độ khung hình chậm hơn nữa và cần chạy nhiều mô phỏng hơn cho mỗi khung hình. Kết quả là hiệu năng ngày càng tệ hơn.

Cuối cùng, khoảng thời gian giữa các lần cập nhật vật lý có thể vượt quá Bước thời gian tối đa cho phép. Sau thời điểm này, Unity bắt đầu bỏ qua các bản cập nhật vật lý và trò chơi bị giật lag.

Để tránh các vấn đề về hiệu năng liên quan đến vật lý:

  • Giảm tần suất mô phỏng. Đối với các nền tảng cấu hình thấp hơn, hãy tăng Fixed Timestep lên một chút so với tốc độ khung hình mục tiêu của bạn. Ví dụ, sử dụng 0,035 giây cho 30ps trên thiết bị di động. Điều này có thể giúp ngăn chặn vòng xoáy suy giảm hiệu suất đó.
  • Giảm số bước thời gian tối đa cho phép . Việc sử dụng giá trị nhỏ hơn (như 0,1 giây) sẽ làm giảm độ chính xác của mô phỏng vật lý, đồng thời cũng giới hạn số lần cập nhật vật lý có thể diễn ra trong một khung hình. Hãy thử nghiệm với các giá trị khác nhau để tìm ra giá trị phù hợp với yêu cầu của dự án.

Nếu cần, hãy mô phỏng bước vật lý thủ công bằng cách chọn SimulationMode trong giai đoạn Cập nhật của khung hình. Điều này cho phép bạn kiểm soát thời điểm thực hiện bước tính toán vật lý. Truyền tham số Time.deltaTime cho Physics.Simulate để giữ cho quá trình vật lý đồng bộ với thời gian mô phỏng. Phương pháp này có thể gây ra sự bất ổn trong mô phỏng vật lý ở những cảnh có vật lý phức tạp hoặc thời gian khung hình thay đổi nhiều, vì vậy hãy sử dụng nó một cách thận trọng.

Tìm hiểu thêm trong tài liệu Physics.Simulate .

Bước thời gian cố định mặc định trong Unity Editor

Giá trị Fixed Timestep mặc định trong Project Settings là 0.02 giây (50 khung hình/giây).

Sử dụng Box Pruning cho các cảnh lớn.

Công cụ vật lý Unity hoạt động theo hai bước:

  • Giai đoạn tổng quát , thu thập các va chạm tiềm năng bằng thuật toán quét và cắt tỉa.
  • Giai đoạn hẹp , nơi mà động cơ thực sự tính toán các va chạm.

Cài đặt mặc định của chế độ BroadPhase (Sweep and Prune BroadPhase) ( Edit > Project Settings > Physics > BroadPhase Type ) có thể tạo ra kết quả sai đối với các thế giới thường bằng phẳng và có nhiều collider. Nếu cảnh của bạn lớn và chủ yếu bằng phẳng, hãy tránh vấn đề này và chuyển sang Automatic Box Pruning hoặc Multibox Pruning Broadphase . Các tùy chọn này chia thế giới thành một lưới, trong đó mỗi ô lưới thực hiện quá trình quét và cắt tỉa.

Chế độ Multibox Pruning của Broadphase cho phép bạn chỉ định thủ công các ranh giới thế giới và số lượng ô lưới, trong khi chế độ Automatic Box Pruning sẽ tự động tính toán điều đó cho bạn.

Xem danh sách đầy đủ các thuộc tính Vật lý tại đây .

Giao diện kiểu pha rộng

Loại pha rộng trong các tùy chọn Vật lý

Điều chỉnh các lần lặp của thuật toán giải

Nếu bạn muốn mô phỏng một đối tượng vật lý cụ thể chính xác hơn, hãy tăng giá trị Rigidbody.solverIterations của nó.

Điều này sẽ ghi đè lên Physics.defaultSolverIterations, mục này cũng có thể được tìm thấy trong Edit > Project Settings > Physics > Default Solver Iterations .

Để tối ưu hóa các mô phỏng vật lý của bạn, hãy đặt giá trị tương đối thấp cho tham số defaultSolveIterations của dự án. Sau đó, áp dụng các giá trị Rigidbody.solverIterations tùy chỉnh cao hơn cho từng trường hợp cần chi tiết hơn.

Tìm hiểu thêm thông tin về Rigidbody.solverIterations .

Số lần lặp mặc định của thuật toán giải

Ghi đè số lần lặp mặc định của bộ giải cho mỗi vật thể cứng

Tắt tính năng đồng bộ hóa chuyển đổi tự động

Theo mặc định, Unity không tự động đồng bộ hóa các thay đổi đối với Transform với công cụ vật lý. Thay vào đó, nó sẽ đợi đến lần cập nhật vật lý tiếp theo hoặc cho đến khi bạn tự gọi Physics.SyncTransforms . Khi tính năng này được kích hoạt, bất kỳ Rigidbody hoặc Collider nào trên Transform đó hoặc các phần tử con của nó sẽ tự động đồng bộ với công cụ vật lý.

Khi nào cần đồng bộ hóa thủ công

Khi tùy chọn autoSyncTransforms bị vô hiệu hóa, Unity chỉ đồng bộ hóa các phép biến đổi trước bước mô phỏng vật lý trong FixedUpdate hoặc khi được yêu cầu rõ ràng thông qua Physics.Simulate. Bạn có thể cần thực hiện thêm các thao tác đồng bộ hóa nếu sử dụng API đọc trực tiếp từ công cụ vật lý giữa các thay đổi Transform và quá trình cập nhật vật lý. Ví dụ bao gồm việc truy cập Rigidbody.position hoặc thực hiện Physics.Raycast .

Thực tiễn tốt nhất về hiệu suất

Mặc dù autoSyncTransforms đảm bảo các truy vấn vật lý luôn được cập nhật, nhưng nó lại gây ra tổn thất về hiệu năng. Mỗi lệnh gọi API liên quan đến vật lý đều buộc phải đồng bộ hóa, điều này có thể làm giảm hiệu suất, đặc biệt là với nhiều truy vấn liên tiếp. Hãy tuân thủ những nguyên tắc thực hành tốt nhất sau đây:

  • Tắt tính năng autoSyncTransforms trừ khi cần thiết : Chỉ bật tính năng này nếu việc đồng bộ hóa chính xác và liên tục là yếu tố then chốt đối với cơ chế trò chơi của bạn.
  • Sử dụng đồng bộ hóa thủ công : Để có hiệu suất tốt hơn, hãy đồng bộ hóa thủ công các Transform bằng Physics.SyncTransforms() trước khi thực hiện các lệnh yêu cầu dữ liệu Transform mới nhất. Cách tiếp cận này hiệu quả hơn so với việc bật autoSyncTransforms trên toàn hệ thống.

Tìm hiểu thêm về Physics.SyncTransforms .

Tính năng tự động đồng bộ đã bị vô hiệu hóa trong một cảnh.

Phân tích hiệu năng của một cảnh trong Unity khi tính năng Auto Sync Transform bị vô hiệu hóa.

Tái sử dụng các hàm gọi lại khi xảy ra xung đột

Mảng tiếp xúc thường nhanh hơn đáng kể, vì vậy khuyến nghị chung là nên sử dụng chúng thay vì tái sử dụng lệnh gọi lại va chạm. Tuy nhiên, hãy cân nhắc những điều sau nếu bạn có trường hợp sử dụng cụ thể cần đến chúng.

Các lệnh gọi lại MonoBehaviour , MonoBehaviour và MonoBehaviour đều nhận một thể hiện va chạm làm tham số. Thể hiện xung đột này được cấp phát trên vùng nhớ heap được quản lý và cần được thu gom rác.

Để giảm lượng rác thải sinh ra, hãy bật Physics.reuseCollisionCallbacks (cũng có trong Cài đặt Dự án > Vật lý > Tái sử dụng hàm gọi va chạm ). Khi kích hoạt tùy chọn này, Unity chỉ gán một cặp va chạm duy nhất cho mỗi hàm gọi lại. Điều này giúp giảm thiểu lượng rác thải cho người thu gom rác và cải thiện hiệu suất.

Khuyến nghị chung là luôn bật tính năng Tái sử dụng các hàm gọi lại khi xảy ra xung đột để đạt được lợi ích về hiệu suất. Bạn chỉ nên vô hiệu hóa tính năng này đối với các dự án cũ mà mã nguồn dựa vào các thể hiện riêng lẻ của lớp Collision, khiến việc lưu trữ các trường riêng lẻ trở nên không khả thi.

Tìm hiểu thêm về Physics.reuseCollisionCallbacks .

Một trường hợp va chạm duy nhất

Trong cửa sổ Unity Console, chỉ có một trường hợp va chạm duy nhất trên Collision Entered và Collision Stay.

Di chuyển các bộ va chạm tĩnh

Các collider tĩnh là GameObjects có thành phần Collider nhưng không có Rigidbody.

Lưu ý rằng bạn có thể di chuyển một collider tĩnh, trái ngược với thuật ngữ "tĩnh". Để làm vậy, chỉ cần thay đổi vị trí của đối tượng vật lý. Tích lũy các thay đổi vị trí và đồng bộ hóa trước khi cập nhật vật lý. Bạn không cần thêm thành phần Rigidbody vào bộ va chạm tĩnh chỉ để di chuyển nó.

Tuy nhiên, nếu bạn muốn bộ va chạm tĩnh tương tác với các vật thể vật lý khác theo cách phức tạp hơn, hãy gán cho nó một Rigidbody động . Hãy sử dụng Rigidbody.position và Rigidbody.rotation để di chuyển đối tượng thay vì truy cập vào thành phần Transform. Điều này đảm bảo hoạt động của hệ thống vật lý sẽ dễ dự đoán hơn.

Ghi chú: Nếu cần di chuyển hoặc cấu hình lại một Static Collider 2D riêng lẻ trong quá trình chạy, hãy thêm thành phần Rigidbody 2D và đặt nó thành Static Body Type, vì việc mô phỏng Collider 2D sẽ nhanh hơn khi nó có Rigidbody 2D riêng. Nếu cần di chuyển hoặc cấu hình lại một nhóm các Collider 2D trong quá trình chạy, sẽ nhanh hơn nếu tất cả chúng đều là con của một Rigidbody 2D cha ẩn duy nhất, thay vì di chuyển từng GameObject riêng lẻ.

Tìm hiểu thêm thông tin về Vật thể rắn .

Sử dụng các truy vấn không cấp phát bộ nhớ

Để phát hiện và thu thập các vật thể va chạm trong các dự án 3D trong một khoảng cách và hướng nhất định, hãy sử dụng raycast và các truy vấn vật lý khác như BoxCast . Lưu ý rằng

Các truy vấn vật lý trả về nhiều collider dưới dạng mảng, chẳng hạn như OverlapSphere hoặc OverlapBox , cần phải cấp phát các đối tượng đó trên heap được quản lý. Điều này có nghĩa là trình thu gom rác cuối cùng cần phải thu hồi các đối tượng đã được cấp phát, điều này có thể làm giảm hiệu năng nếu xảy ra vào thời điểm không thích hợp.

Để giảm thiểu chi phí phát sinh, hãy sử dụng các phiên bản NonAlloc của các truy vấn đó. Ví dụ, nếu bạn đang sử dụng OverlapSphere để thu thập tất cả các điểm va chạm tiềm năng xung quanh một điểm, hãy sử dụng OverlapSphereNonAlloc thay thế.

Điều này cho phép bạn truyền vào một mảng các collider (kết quả).tham số) để hoạt động như một bộ đệm. Phương thức NonAlloc hoạt động mà không tạo ra rác. Ngược lại, nó hoạt động giống như phương thức phân bổ tương ứng.

Lưu ý rằng bạn cần định nghĩa một vùng đệm kết quả có kích thước đủ lớn khi sử dụng phương thức NonAlloc. Bộ đệm sẽ không tự động mở rộng nếu hết dung lượng.

Vật lý 2D

Lưu ý rằng lời khuyên trên không áp dụng cho các truy vấn vật lý 2D , vì trong hệ thống vật lý 2D của Unity, các phương thức không có hậu tố "NonAlloc". Thay vào đó, tất cả các phương thức vật lý 2D , bao gồm cả những phương thức trả về nhiều kết quả, đều cung cấp các phiên bản quá tải chấp nhận mảng hoặc danh sách. Ví dụ, trong khi hệ thống vật lý 3D có các phương thức như RaycastNonAlloc, thì phiên bản tương đương 2D chỉ đơn giản sử dụng một phiên bản quá tải của Raycast có thể nhận một mảng hoặc List làm tham số, chẳng hạn như:

var results = new List();

int hitCount = Physics2D.Raycast(origin, direction, contactFilter, results);

Bằng cách sử dụng các hàm quá tải, bạn có thể thực hiện các truy vấn không cấp phát bộ nhớ trong hệ thống vật lý 2D mà không cần đến các phương thức NonAlloc chuyên dụng.

Tìm hiểu thêm trong tài liệu về phương thức NonAlloc .


Truy vấn hàng loạt cho dò tia

Bạn có thể chạy các truy vấn tia bằng Physics.Raycast . Tuy nhiên, nếu bạn có số lượng lớn các thao tác dò tia (ví dụ: tính toán tầm nhìn cho 10.000 tác nhân), điều này có thể tiêu tốn một lượng thời gian xử lý CPU đáng kể.

Sử dụng RaycastCommand để nhóm các truy vấn bằng Hệ thống Job C#. Điều này giúp giảm tải công việc cho luồng chính, cho phép thực hiện các phép dò tia một cách bất đồng bộ và song song.

Xem ví dụ trong tài liệu về RaycastCommands .

Trực quan hóa bằng Trình gỡ lỗi vật lý

Sử dụng cửa sổ Gỡ lỗi Vật lý ( Cửa sổ > Phân tích > Trình gỡ lỗi Vật lý ) để giúp khắc phục mọi sự cố liên quan đến các bộ va chạm hoặc sự không nhất quán. Hình ảnh này hiển thị chỉ báo mã màu cho GameObjects có thể va chạm với nhau.

Để biết thêm thông tin chi tiết, vui lòng xem tài liệu hướng dẫn về Physics Debugger .

Giao diện gỡ lỗi vật lý

Thêm mẹo dành cho các nhà phát triển và người sáng tạo Unity

Tìm hiểu thêm các phương pháp hay nhất và mẹo hữu ích từ trung tâm hướng dẫn thực hành tốt nhất Unity . Hãy lựa chọn từ hơn 30 hướng dẫn được tạo ra bởi các chuyên gia trong ngành, các kỹ sư và nghệ sĩ kỹ thuật Unity , giúp bạn phát triển hiệu quả với bộ công cụ và hệ thống của Unity.