Как указано в комментариях, Unity реализовала 2 основных метода для логики инициализации MonoBehaviour: Запуск и Пробуждение .
Существуют недостатки этих 2 методов инициализации:
- Они не могут принять ни один параметр
- Вы не уверены в порядке их выполнения
Существует стандартный порядок выполнения и из этого вы можете быть уверены, что Start выполняется после Awake.Но если у вас есть несколько вариантов MonoBehaviours одного и того же типа, то будет нелегко отследить, какой из них выполняется первым.
Если ваша проблема - просто порядок выполнения, а у вас разные типы, вы можете просто обновить скрипт порядок выполнения .
В противном случае существуют дополнительные подходы, позволяющие избежать обоих недостатков, с использованием метода Factory внутри монобиха.
Учтите, что в этом случае порядок выполнения будет:
Пробуждение => OnEnable => Сброс => Запуск => МЕТОД ВАШЕГО ИНИЦИАТИРОВАНИЯ
ЧАСТНЫЙ ЗАВОДСКИЙ СПОСОБ
public class YourMono : MonoBehaviour
{
//a factory method with the related gameobject and the init parameters
public static YourMono AddWithInit(GameObject target, int yourInt, bool yourBool)
{
var yourMono = target.AddComponent<YourMono>();
yourMono.InitMonoBehaviour(yourInt, yourBool);
return yourMono;
}
private void InitMonoBehaviour(int yourInt, bool yourBool)
{
//init here
}
}
Этот метод обеспечивает лучшую инкапсуляцию, поскольку мы можем быть уверены, что InitMonoBehaviour будет вызываться только один раз.
ФАБРИКА РАСШИРЕНИЯ
Вы также можете создать фабрику из расширения,В этом случае вы удаляете фабричный метод из класса, может быть полезно отделить фабричную логику от логики игрового процесса.
Но в этом случае вам нужно будет сделать InitMonoBehaviour внутренним и реализоватьрасширение в том же пространстве имен.
В результате InitMonoBehaviour будет немного более доступным (внутренне из того же пространства имен), поэтому он имеет более низкую инкапсуляцию.
[Serializable]
public class YourData
{
}
namespace YourMonoNameSpace.MonoBehaviourFactory
{
public static class MonoFactory
{
public static YourMono AddYourMono(this GameObject targetObject, YourData initData)
{
var yourMono = targetObject.AddComponent<YourMono>();
yourMono.InitMonoBehaviour(initData);
return yourMono;
}
}
}
namespace YourMonoNameSpace
{
public class YourMono : MonoBehaviour
{
private YourData _componentData= null;
internal void InitMonoBehaviour(YourData initData)
{
if(_componentData != null ) return;
_componentData = initData;
}
}
}
При этом обе эти опции также имеютнедостаток:
- Кто-то может забыть запустить их.
Итак, если вы хотите, чтобы этот метод был «обязательным», а не необязательным, я предлагаю добавить флаг bool_Известно, чтобы никто не забыл его реализовать.
ВСТУПЛЕНИЕ УПРАВЛЕНИЯ - ВНУТРИ БУДУЩЕГО
Лично я бы реализовал логику с Scriptable Object или с Singleton , и я бы вызвал его во время пробуждения, чтобы убедиться, что инициализация вызывается все время.
public class YourMonoAutoInit : MonoBehaviour
{
public InitLogic _initializationLogic;
//a factory method with the related gameobject and the init parameters
public void Awake()
{
//make sure we not miss initialization logic
Assert.IsNotNull(_initializationLogic);
InitMonoBehaviour(_initializationLogic);
}
private void InitMonoBehaviour(InitLogic initializationLogic)
{
//init here using
int request = initializationLogic.currentRequest;
bool playerAlive = initializationLogic.playerIsAlive;
}
}
public class InitLogic : ScriptableObject
{
public int currentRequest = 1;
public bool playerIsAlive = false;
}
//this is another monobehaviour that might access the player state and change it
public class KillPlayer : MonoBehaviour
{
public InitLogic playerState;
public void KillThisPlayer() => playerState.playerIsAlive = false;
}
С этой последней версией yВы достигаете инверсии управления.
Поэтому вместо УСТАНОВКИ ДАННЫХ В MONOBEHAVIOUR:
//SETTING DATA FROM CLASS TO MONOBEHAVIOUR
public class OtherScript : MonoBehaviour
{
private void CreateMonoBehaviour() => YourMono.AddWithInit(gameObject, 1, true);
}
Вы ПОЛУЧИТЕ ДАННЫЕ В МОНОВОБСТВЕННОМ ИЗ КЛАССА.
//GETTING IN MONOBEHVARIOUS FROM CLASS
public class YourOtherMono : MonoBehaviour
{
public YourData data;
private void Awake()
{
(int yourInt, bool yourBool) = data.GetData();
//do something with the data received
}
}