Чому Unity використовує роздуми, щоб отримати метод оновлення?


12

Чому Unity використовувати відображення для того , щоб доступ до MonoBehaviourметодам повідомлення , як Awake, Update, Start, ...?

Чи не буде повільно використовувати рефлексію? Чому він не використовує інші підходи, як Template Method? Він може просто визначити методи як абстрактні в MonoBehaviourбазовому класі і змусити підкласи до його реалізації.

Відповіді:


20

Це не так

Як називається оновлення

Ні, Unity не використовує System.Reflection, щоб знайти магічний метод кожного разу, коли йому потрібно зателефонувати.

Натомість, при першому зверненні до MonoBehaviour заданого типу перевіряється базовий сценарій за допомогою сценарію виконання (або Mono, або IL2CPP), чи є визначені якісь магічні методи, і ця інформація кешується. Якщо MonoBehaviour має певний метод, він додається до відповідного списку, наприклад, якщо у сценарії визначено метод оновлення, він додається до списку сценаріїв, які потрібно оновлювати кожен кадр.

Під час гри Unity просто перебирає ці списки і виконує методи з неї - це дуже просто. Крім того, це не має значення, чи ваш метод оновлення є приватним чи приватним.

Що стосується причин , які робляться таким чином, я багато в чому віднесу вас (читача) до відповіді DMGregory , яка зводиться до балансу двох конкуруючих речей:

  1. Оптимізація продуктивності
  2. Простота використання нових розробників

Новий розробник просто хоче, щоб він працював, і не хоче з'ясовувати, "як я це підключую до системи подій?" але це все одно має працювати швидко з мінімальними накладними витратами.

Рішення, мабуть, найкраще, що може бути досягнуто в рамках цих двох обмежень. Або, принаймні, на той час змогла придумати найкраща команда розробників Unity. Ми може ніколи не дізнаємось.


2
tl; dr той самий процес, інший, швидший API. Але чому вони не обрали інший метод, як просили ОП?
wondra

10
Не слід заперечувати можливість простої старої причини «поганого дизайну». Після виходу вихідного коду c # користувачі виявили безліч помилок і незрозумілих дизайнерських рішень. Деякі гамедеси нарешті змогли зрозуміти ті несподівані поведінки, з якими вони боролися роками.
Екеріон

Окрім технічних питань, це перше, чому навчаються новачки, тому додати або пропустити їх потрібно легко.
Нікаас

6
Можуть бути і історичні причини такої конструкції. Єдність розпочалася зі своєї мови сценаріїв, яку вони потім поступово припиняли на користь C #. Цілком природно, що вони хотіли продовжувати використовувати ті самі шаблони, навіть якщо це означало трохи обдурити.
Філіпп

3
Я думаю, що ми можемо корисно відповісти "Що робить Єдність цими засобами" - наприклад. яка перевага перед колекцією абстрактних публічних методів, які всі повинні бути реалізовані. Ми не можемо відповісти, "на що думали біси" Єдності "? але ми можемо вирішити питання "чому такий підхід корисний для користувачів двигуна?"
DMGregory

10

Він може просто визначити методи абстрактними в базовому класі MonoBehaviour і змусити підкласи до його реалізації.

Однією з переваг системи, яку Unity використовує, є те, що вам не доведеться реалізовувати всі повідомлення MonoBehaviour, яких налічується понад 60 .

Зазвичай нам просто потрібна одна чи маленька жменька цих методів. Оскільки деякі специфічні для 2D / 3D фізики, деякі унікальні для камер або систем часток, малоймовірно, що будь-який один сценарій коли-небудь знадобиться їм.

Залишаючи повідомлення, які нам не потрібні як незавершені, ми можемо чітко сигналізувати під час виконання: "навіть не турбуйся про те, щоб викликати OnCollisionStay2D на цьому об'єкті - мені це не потрібно"

Це може бути значним виграшем ефективності. Тепер двигун може відфільтрувати короткий список, щоб викликати Оновлення лише на ~ 20 об'єктах моєї сцени, для яких потрібна спеціальна логіка оновлення кожного кадру, а не всі ~ 200 об'єктів, які складають усі пейзажі або реагують лише на фізичні події.


Лише питання ... наскільки я знаю (не особисто), якщо у вас є тисячі GameObjects, які використовують сценарій із методом оновлення, у вас є значні наслідки для продуктивності. Альтернативою є використання списків та повторення через них лише одним методом оновлення в сценарії менеджера, який здається значно ефективнішим. Це все ще так, чи це вже змінилося? - Якщо нічого не змінилося, це означало б, що спосіб Unity зробити це ніде не є оптимальним щодо продуктивності.
Битва

4
@Battle, що ви описуєте, відповідає посиланню, яке цитує Draco18s з 2015 року, і я б підозрював, що це все-таки правда. Можливість залишати метод оновлення невизначеним для цих тисяч об'єктів саме те, що дозволяє цій оптимізації працювати. Якби кожен MonoBehaviour мав метод оновлення, визначений за допомогою абстрактного базового класу, як описано в розділі питання, який я цитував, ми б не мали можливості обмежувати наші виклики оновлення лише ітерацією списку менеджера. Зауважте, що це питання не відповідає "Чи оптимальний підхід Unity?" але лише тим, яким може бути корисний сучасний підхід.
DMGregory

Так, я бачу, це має сенс. Дякую за відповідь!
Битва

@Battle Це все-таки вірно. Хоча річ, яку робить Unity, є більш ефективною, ніж альтернативи, вона все ще має більше накладних витрат, ніж звичайний виклик функції.
Draco18s більше не довіряє SE

@ Draco18s - Так. Я вже впровадив UpdateManager для своїх проектів, який давно піклується про цю оптимізацію. Я просто хотів певного підтвердження, що воно все-таки потрібне / корисне.
Битва
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.