Який із цих двох кодів "кращий"? Зробити локальну змінну чи змінну класу?


11

Я роблю більше ігор і задаю дурніші запитання.

Сподіваємось, цей дуже короткий. Я створюю дуже базовий клас, який просто переміщує об’єкт Player, застосовуючи силу до жорсткого тіла, але мені стало цікаво, чи слід робити класне посилання на rb або просто локальну змінну всередині Оновлення кожного кадру? (маючи на увазі, це вже існує в батьківському класі Monobehaviour.GameObject.

Мені цікаво, якщо виконання багатьох локальних змінних уповільнить цикл у цілому (під локальним я маю на увазі всередині самої функції, а не на вершині класу - сподіваюся, що ми використовуємо правильний термін).

Ось що я маю на увазі, два способи, які я думав зробити це:

public class Player : MonoBehaviour {

private void FixedUpdate()
{
    Rigidbody rb = GetComponent<Rigidbody>();

    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

або ...

public class Player : MonoBehaviour {
Rigidbody rb;

private void Awake()
{
    rb = GetComponent<Rigidbody>();
}

private void FixedUpdate()
{
    float v = Input.GetAxis("Vertical");

    rb.AddForce(v * rb.transform.forward * Const.walkForce);
}
}

4
Це більше схоже на питання для перегляду коду SE.
Орфевс

1
Ви також можете зробити власність класу float va.
Чад

Я, мабуть, зрештою буду Чадом, тому що буду використовувати його у двох методах у класі. Це було дійсно просто простим кодом, щоб отримати запитання про змінні локальних проти класів поперек, не здуваючи його з великою кількістю коду. Мені дуже подобається зберігати змінні локальними (і «не в дорозі» як там!), Але, звичайно, я повинен переконатися, що я не починаю дублювати речі, а не мати одну змінну класу для кожної.
Big T Larrity

Фрагмент коду не є «кодом». Запитання про те, "який код краще", змушує вас виглядати любителем.
Майлз Рут

1
Я любитель, тож зі мною чудово дякую Майлз
Big T Larrity

Відповіді:


25

Взагалі, я виявив, що ви повинні розміщувати дані якомога вужче, щоб почати і розширити область, як ви виявите, що вам потрібно. Це означає, що якщо ви можете зробити його локальною змінною замість члена, ви, ймовірно, повинні почати з цього місця.

Це пояснюється тим, що вузька сфера зменшує кількість місць у коді, де потрібно обґрунтувати ці дані, і, таким чином, зменшиться кількість місць, які ви можете неправильно пояснити (що призводить до помилок).

Власне декларування локальних змінних ніколи не сприймає ефективності: вони дешеві, а сучасні компілятори можуть навіть оптимізувати "додаткові".

Ініціалізація їх може викликати занепокоєння; у вашому випадку ваше жорстке тіло піднімається щоразу через GetComponent, що має деяку ненульову вартість. Якщо ви знаєте, що жорсткий компонент корпусу не зміниться для цього конкретного ігрового об’єкта, ви можете переглянути його один раз і зберегти результат у змінній учасника та уникнути невеликих накладних витрат на виклик.

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

Отже, підсумовуючи: загалом, за замовчуванням робити речі максимально локальними, але в цьому випадку, мабуть, розумно зробити rbчлен, щоб ви могли здійснити пошук один раз Awakeі уникати необхідності робити кожен FixedUpdateвиклик.


1
дякую Джошу, я відчував, що краще буде ініціалізувати rb лише один раз, і дуже дякую за чітке пояснення чому. Приємно знати напевно, ви бачите, що я не був на 100% впевнений, що GetComponent розраховується як ініціалізація кожного разу, або просто "переглядаючи його" від Monobehaviour. Але зараз я отримую це велике спасибі за надшвидку корисну відповідь
Big T Larrity

1
@SuperMegaBroBro GetComponent це досить швидко - ви б важко зробити якісь - або пошуку , який має порівнянну швидкість. Якщо у вас немає даних про ефективність, які дозволяють стверджувати, що це проблема, дотримуйтесь підходу "зберігати речі локальні". Ви завжди можете її оптимізувати пізніше. Див answers.unity.com/questions/185164 / ... Не забувайте , що кешування не є безкоштовним або - якщо ви кешувати кожен GetComponentу вашій грі, то це , ймовірно , буде чистий збиток. Виміряйте. Визначте, де варті оптимізації. Зосередьтеся на створенні чудової гри :)
Luaan

1
Основна суть, яку ви повинні відмовитись від цієї відповіді (що досить добре) полягає в наступному: Якщо ви хочете шукати код, який найпростіше обґрунтувати, протестувати і переконатися, що він не містить помилок, візьміть локальну змінну. Але, як завжди, нам іноді потрібно робити жертви для вдосконалення коду з міркувань продуктивності, тому член класу може бути доречним (але по-перше, не потрібно просто робити передчасну оптимізацію).
Полігном

велике спасибі хлопці, особливо Луаану, оскільки мені було цікаво про те питання "кешування", поки я написав оригінальне запитання (але я насправді не знав, як це сказати). Я, безумовно, максимально прийму «місцевий» підхід. дякую за всю чудову допомогу, як звичайні хлопці.
Big T Larrity

2

Відповідь Джоша Петрі дуже хороша - ось додаткова перспектива.

Коли ви працюєте з кодом, який ви досить добре розумієте домен, ви можете застосувати змінні місця, де вони мають сенс.

Наприклад, якщо у мене є Personклас з waveGoodbyeметодом, можливо, мій клас раніше не мав handоб'єкта, і я можу оголосити його локально waveGoodbye. Тепер тут очевидно, що у людини є рука, тому ви, природно, можете заявити про це як про члена, Personне замислюючись над цим, але це ж питання стосується.

Якщо ви заявляєте на handмісцевому рівні, то пізніше ви можете додати karateChopметод, який також потребує допомоги. Це коли декларування змінних на локальному рівні може стати проблематичним - адже молодші розробники часто відступають від копіювання / вставки декларації, waveGoodbyeі тепер у вас є одна і та ж концепція, розташована у двох місцях. Будь-які зміни handтоді потрібно змінити в обох місцях, і таким чином починається пагорб мурашиних помилок.

Так що загалом,

  1. Якщо ви впевнені у розміщенні декларації, додайте її до місця, де це має сенс.

  2. Якщо ви не впевнені в собі, тоді запускайте локальний і не забудьте зробити рефактор, коли ви отримаєте потік повторного використання коду.

Редагувати: О, і не робіть тієї самої помилки, я витрачаю занадто багато часу на з'ясування, де розмістити ваші декларації. Важко зрозуміти структуру ваших даних наперед, і під час написання коду структура має спосіб розкрити себе.


2
Крім того , з речі природно впорядкованими, як кожен Personповинен мати елемент , hand якщо його ставлення в застосуванні, часто допомагає іншим розробникам ( в більшості випадків вам через 6 місяців) , щоб краще зрозуміти код. У цьому випадку, здається, логічно бути Rigidbodyчленом вашого Playerі, я кажу більше, навіть якщо це передбачає гірші показники роботи. У відеоіграх, що є важливим для розгляду, але я думаю, що в коді , щоб бути зрозумілим, часто важливіше
alseether

1
відмінні відповіді дякую хлопці. Я не намагаюся звучати як всезнай, але всі ці відповіді ще раз підтвердили те, про що я вже думав, тож колись я дуже радий і добрий прогрес у своїх іграх. Зараз я роблю 3D-футбольну гру з належною анімацією та всім, роблю справжні успіхи: D скоро мені тут буде потрібна допомога щодо того, як зробити її двома гравцями, і наважуся сказати онлайн-mulitplayer: D весело, хлопці і ще раз дякую!
Big T Larrity
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.