Tại sao Unity sử dụng sự phản chiếu để có được phương thức cập nhật?


11

Tại sao Unity phản ánh sử dụng để truy cập MonoBehaviourcác phương pháp thông báo như Awake, Update, Start, ...?

Nó sẽ không chậm để sử dụng sự phản chiếu? Tại sao nó không tận dụng các cách tiếp cận khác như thế Template Methodnào? Nó chỉ đơn giản có thể định nghĩa các phương thức là trừu tượng trong MonoBehaviourlớp cơ sở và buộc các lớp con thực hiện nó.

Câu trả lời:


19

Nó không

Cách cập nhật được gọi

Không, Unity không sử dụng System.Reflection để tìm phương thức ma thuật mỗi khi cần gọi một phương thức.

Thay vào đó, lần đầu tiên MonoBehaviour của một loại nhất định được truy cập, tập lệnh cơ bản được kiểm tra thông qua thời gian chạy tập lệnh (Mono hoặc IL2CPP) cho dù nó có bất kỳ phương thức ma thuật nào được xác định và thông tin này được lưu trữ. Nếu MonoBehaviour có một phương thức cụ thể, nó sẽ được thêm vào danh sách phù hợp, ví dụ: nếu tập lệnh có phương thức Cập nhật được xác định, nó sẽ được thêm vào danh sách các tập lệnh cần được cập nhật mỗi khung.

Trong trò chơi, Unity chỉ lặp đi lặp lại qua các danh sách này và thực hiện các phương thức từ nó - đơn giản. Ngoài ra, đây là lý do tại sao nó không quan trọng nếu phương pháp Cập nhật của bạn là công khai hoặc riêng tư.

Đối với các lý do được thực hiện theo cách này, phần lớn tôi sẽ giới thiệu cho bạn (người đọc) câu trả lời của DMGregory , trong đó có sự cân bằng của hai điều cạnh tranh:

  1. Tối ưu hóa hiệu suất
  2. Dễ sử dụng nhà phát triển mới

Một nhà phát triển mới chỉ muốn nó hoạt động và không muốn phải tìm ra "làm thế nào để tôi kết nối điều này với hệ thống sự kiện?" nhưng nó vẫn nên chạy nhanh với chi phí tối thiểu.

Giải pháp có lẽ là tốt nhất có thể đạt được trong hai hạn chế này. Hoặc ít nhất, điều tốt nhất mà nhóm phát triển Unity có thể đưa ra vào thời điểm đó. Chúng tôi có thể không bao giờ biết.


2
tl; dr cùng một quá trình, API khác nhau, nhanh hơn. Nhưng tại sao họ không chọn một phương pháp khác như yêu cầu của OP?
wonderra

10
Chúng ta không nên phủ nhận khả năng của lý do "thiết kế xấu" cũ. Sau khi phát hành c # mã nguồn người dùng đã tìm thấy tấn của những sai lầm và quyết định thiết kế không giải thích được. Một số gamedev cuối cùng đã có thể hiểu những hành vi bất ngờ mà họ đã chiến đấu trong nhiều năm.
Xuất hành

Về mặt kỹ thuật, đây là một trong những điều đầu tiên người mới học, vì vậy nó phải dễ dàng để thêm hoặc bỏ qua.
Nikaas

6
Cũng có thể có những lý do lịch sử cho thiết kế này. Unity bắt đầu với ngôn ngữ kịch bản của riêng họ, sau đó họ dần dần loại bỏ C #. Điều tự nhiên là họ muốn tiếp tục sử dụng các mẫu tương tự, ngay cả khi nó có nghĩa là gian lận một chút.
Philipp

3
Tôi nghĩ rằng chúng ta có thể trả lời một cách hữu ích "Unity hoàn thành điều gì có nghĩa là gì" - vd. lợi thế của một bộ sưu tập các phương pháp công cộng trừu tượng phải được thực hiện. Chúng tôi không thể trả lời "các nhà phát triển Unity nghĩ gì?" nhưng chúng ta có thể giải quyết "tại sao cách tiếp cận này hữu ích cho người dùng động cơ?"
DMGregory

9

Nó chỉ đơn giản có thể định nghĩa các phương thức là trừu tượng trong lớp cơ sở MonoBehaviour và buộc các lớp con thực hiện nó.

Một trong những lợi thế của hệ thống mà Unity sử dụng là bạn không phải triển khai mọi tin nhắn MonoBehaviour, trong đó có hơn 60 .

Thông thường chúng ta chỉ cần một hoặc một số ít các phương pháp này. Vì một số đặc trưng cho vật lý 2D / 3D, một số duy nhất cho máy ảnh hoặc hệ thống hạt, rất khó có thể có bất kỳ tập lệnh nào sẽ cần tất cả chúng.

Bằng cách để lại các tin nhắn mà chúng tôi không cần như chưa thực hiện, chúng tôi có thể báo hiệu rõ ràng cho thời gian chạy "thậm chí không bận tâm gọi OnCollisionStay2D trên đối tượng này - tôi không cần nó"

Đây có thể là một chiến thắng hiệu quả đáng kể. Bây giờ, công cụ có thể lọc một danh sách ngắn để gọi Cập nhật chỉ ~ 20 đối tượng trong cảnh của tôi cần cập nhật logic tùy chỉnh mọi khung hình, và không phải tất cả ~ 200 đối tượng tạo nên tất cả cảnh vật hoặc chỉ phản ứng với các sự kiện vật lý.


Chỉ là một câu hỏi ... theo như tôi biết (không phải cá nhân), nếu bạn có hàng ngàn GameObject, tất cả đều sử dụng tập lệnh với phương thức Cập nhật, bạn có tác động hiệu suất đáng kể. Cách khác là sử dụng danh sách và lặp qua chúng chỉ với một phương thức Cập nhật trong tập lệnh trình quản lý, có vẻ như hiệu quả hơn đáng kể. Đó vẫn là trường hợp, hoặc đã thay đổi? - Nếu không có gì thay đổi, điều đó có nghĩa là cách thức của Unity để thực hiện nó không ở đâu gần tối ưu về hiệu suất.
Trận chiến

3
@ Làm việc với những gì bạn mô tả phù hợp với liên kết mà Draco18 trích dẫn từ năm 2015 và tôi nghi ngờ đó vẫn là sự thật. Có thể để phương thức Cập nhật không xác định trên hàng ngàn đối tượng đó chính xác là điều cho phép tối ưu hóa này hoạt động. Nếu mọi MonoBehaviour đều có phương thức Cập nhật được xác định thông qua lớp cơ sở trừu tượng như được mô tả trong phần câu hỏi tôi đã trích dẫn, thì chúng tôi sẽ không có khả năng giới hạn các lệnh gọi cập nhật của mình chỉ trong vòng lặp danh sách của người quản lý. Lưu ý rằng Q & A này không giải quyết "Cách tiếp cận của Unity có tối ưu không?" nhưng chỉ làm thế nào cách tiếp cận hiện tại có thể có ích.
DMGregory

Ah tôi hiểu rồi, điều đó thực sự có ý nghĩa. Cảm ơn câu trả lời!
Trận chiến

@Băng Nó vẫn đúng. Mặc dù điều Unity thực hiện có hiệu suất cao hơn các lựa chọn thay thế nhưng nó vẫn có nhiều chi phí hơn so với một cuộc gọi chức năng thông thường.
Draco18 không còn tin tưởng SE

@ Draco18s - Vâng. Tôi đã triển khai một Trình quản lý cập nhật cho các dự án của mình, nó đảm nhiệm việc tối ưu hóa đó từ lâu. Tôi chỉ muốn một số xác nhận rằng nó vẫn cần thiết / hữu ích.
Trận chiến
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.