Существует ли такая вещь, как слишком большое кэширование в сценариях с монохарактеристиками?

#c# #unity3d

#c# #unity3d

Вопрос:

Мои скрипты, как правило, до краев заполнены ссылками на кэшированные компоненты, такими как это:

 using Scripts.Combat;
using Scripts.Core;
using Scripts.Movement;
using UnityEngine;

namespace Scripts.Control
{
    public class AIController : MonoBehaviour
    {
        [SerializeField] float chaseRadius = 5f;
        [SerializeField] float suspicionTime = 3f;

        GameObject _player;
        Fighter _fighter;
        Health _health;
        Mover _mover;
        ActionScheduler _actionScheduler;

        Vector3 _guardPosition;
        float _timeSinceLastSawPlayer = Mathf.Infinity;

        void Start()
        {
            AssignVariables();
        }

        void AssignVariables()
        {
            _player = GameObject.FindWithTag("Player");
            _fighter = GetComponent<Fighter>();
            _health = GetComponent<Health>();
            _mover = GetComponent<Mover>();
            _actionScheduler = GetComponent<ActionScheduler>();
            
            _guardPosition = transform.position;
        }
  

Для меня это просто кажется загроможденным и шумным. Действительно ли это наиболее эффективный способ решения проблемы отсутствия вызовов GetComponent<>() в ваших методах Update()?

Комментарии:

1. Нет. Это нормально. Единственное, что нужно спросить себя, не слишком ли много делает этот скрипт, должен ли я использовать в нем меньше и более конкретные сценарии, которые затем становятся повторно используемыми

Ответ №1:

Что касается «стандартного способа», то нет — нет другого «лучшего» способа или более производительного

Если вы можете немного снизить производительность своего кода для кэширования, вы можете создать внедрение зависимостей. Здесь автор подробно рассказывает о том, как это может работать, и каковы недостатки такой системы.

Пример того, как может работать внедрение зависимостей.

 //pseudo-code you would put into Awake or Start or wrap in another class
var fields = GetType().GetFields(BindingFlags.Instance);
foreach(var field in fields)
{
    if(typeof(MonoBehaviour).IsAsignableFrom(field.FieldType))
    {
        //Add better handling for different types, or array of components
        field.SetValue(this, GetComponent(field.FieldType));
    }
}
  

Вы можете пойти другим путем и избавиться от компонентов с помощью нового подхода, который вообще не использует монохарактеристики и компоненты, — это система компонентов объекта. Но это полный сдвиг в том, как вы программируете свою игру.

Комментарии:

1. ECS взорвал мой разум. Если кто-нибудь еще найдет этот пост, пожалуйста, загляните в ECS как можно скорее.

2. Пожалуйста, имейте в виду, что по состоянию на 2020 год это все еще НЕ готово к производству, но я бы сказал, что на данный момент это довольно удобно

3. Не только это, отсутствие документации, вероятно, затруднит большинству пользователей доступ к ней в данный момент в любом случае. но я определенно думаю, что любой, кто заинтересован в создании игр с Unity в долгосрочной перспективе, должен начать читать сейчас и немного повозиться с ним здесь и там, пока он не станет полностью готовым к производству. Прирост производительности до 100 раз — это довольно безумно..