Я делаю больше игр и задаю более глупые вопросы.
Надеюсь, это очень кратко. Я делаю очень простой класс, который просто перемещает объект Player, применяя силу к жесткому телу, но меня удивляет, должен ли я делать ссылку на класс на rb или просто на локальную переменную внутри Обновлять каждый кадр? (имея в виду, что он уже существует в родительском классе Monobehaviour.GameObject Unity).
Мне интересно, если много локальных переменных замедлило бы цикл в целом (под локальным я подразумеваю саму функцию, а не верхнюю часть класса - надеюсь, я использую правильный термин).
Вот что я имею в виду, два способа, которыми я думал об этом:
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);
}
}
Ответы:
В общем, я обнаружил, что для начала вы должны охватывать данные настолько узко, насколько это возможно, и расширять объем по мере необходимости. Это означает, что если вы можете сделать это локальной переменной вместо члена, вы, вероятно, должны начать там.
Это связано с тем, что более узкая область действия уменьшает количество мест в коде, в которых вы должны рассуждать об этих данных, и, таким образом, уменьшает количество мест, в которых вы можете рассуждать неправильно (что приводит к ошибкам).
Фактически объявление только локальных переменных никогда не станет проблемой производительности: они дешевы, а современные компиляторы могут даже оптимизировать «дополнительные функции».
Инициализация их может быть проблемой; в вашем случае ваше твердое тело ищется каждый раз через
GetComponent
, что имеет некоторую ненулевую стоимость. Если вы знаете, что компонент твердого тела не изменится для этого конкретного игрового объекта, вы можете посмотреть его один раз и сохранить результат в переменной-члене и избежать небольшого количества накладных расходов на каждый вызов.Маловероятно, что издержки для каждого вызова будут значительными в этом случае, но со временем выполнение этого для многих компонентов может сложиться. Вы бы хотели применить профилировщик, чтобы быть уверенным.
Итак, подведем итог: в общем, по умолчанию все делается как можно более локальным, но в этом случае, вероятно, разумно сделать
rb
член, чтобы вы могли выполнить поиск один разAwake
и избежать необходимости делать это каждыйFixedUpdate
вызов.источник
GetComponent
работает довольно быстро - вам будет сложно сделать любой поиск с сопоставимой скоростью. Если у вас нет данных о производительности, свидетельствующих о том, что это проблема, придерживайтесь подхода «держите вещи локально». Вы всегда можете оптимизировать это позже. См. Answers.unity.com/questions/185164/… Не забывайте, что кеширование тоже не бесплатно - если вы кешируете всеGetComponent
в своей игре, это, вероятно, будет чистым убытком. Мера. Определите, где оптимизация того стоит. Сосредоточьтесь на создании отличной игры :)Ответ Джоша Петри очень хороший - вот дополнительная точка зрения.
Когда вы работаете с кодом, который вы достаточно хорошо понимаете в области, вы можете использовать переменные там, где они имеют смысл.
Например, если у меня есть
Person
класс сwaveGoodbye
методом, возможно, у моего класса раньше не былоhand
объекта, и поэтому я мог бы объявить его локально вwaveGoodbye
. Теперь здесь очевидно, что у человека есть рука, поэтому вы можете, естественно, объявить ее членом,Person
не задумываясь об этом, но проблема та же.Если вы объявите
hand
локально, то позже вы можете добавитьkarateChop
метод, который также требует руки. Это происходит, когда объявление переменных локально может стать проблематичным - потому что начинающие разработчики часто прибегают к копированию / вставке объявления,waveGoodbye
и теперь у вас одна и та же концепция, расположенная в двух местах. Любые измененияhand
должны быть изменены в обоих местах, и, таким образом, начинается ошибкамуравейника.В общем,
Если вы уверены в размещении своей декларации, поместите ее туда, где это имеет смысл.
Если вы не уверены в себе, то начните с локального и убедитесь, что вы проведете рефакторинг, когда получите повторное использование кода.
Редактировать: Да, и не делайте ту же ошибку, что я потратил слишком много времени, чтобы выяснить, где охватить ваши декларации. Трудно понять структуру ваших данных заранее, и когда вы пишете свой код, структура имеет способ раскрыть себя.
источник
Person
должен иметь члена,hand
если он имеет отношение к приложению, часто помогает другим разработчикам (чаще всего вам через 6 месяцев) лучше понимать код. В этом случае кажется логичным иметь вRigidbody
качестве члена вашей группыPlayer
и, я бы сказал, больше, даже если это подразумевает худшую производительность. В видеоиграх это важный момент для рассмотрения, но я думаю, что в коде ясность часто важнее