0
\$\begingroup\$

I have three scritps and one plain C# class.
EnemyMonobehaviour, EnemyAttackMonobehaviour and UnitState plain class.

In enemyMono I have Initialize function that initializes unitState.

public void Initialize(float moveSpeed, Transform[] waypoints,  
    Damage damage, Armor armor, Health health, float magicalResistance, int bounty) {
    
    this.unitState = new UnitState(damage, armor, health, magicalResistance);

    this.bounty = bounty;

    GetComponent<EnemyFollowPath>().Initialize(moveSpeed, waypoints);
}

I have a WaveManager class that spawns different enemies and than later it initializes them.

GameObject enemyUnit = container.InstantiatePrefab(enemy.prefab, spawningPoint, Quaternion.identity, null);
enemyUnit.GetComponent<Enemy>().Initialize(2f, EnemyPath.Instance.getWaypoints(), 
            new Damage(enemy.damageType, enemy.attackType, enemy.minDamage, enemy.maxDamage),
            new Armor(enemy.armorType, enemy.armor), 
            new Health(enemy.maxHealth), 10, enemy.bounty);

And now here is where the problem appears. EnemyAttack is initialized like this

private void Awake() {
    this.enemy = GetComponent<Enemy>();

    IUnitState unitState = enemy.GetState();

    minDamage = unitState.GetDamage().minDamage;
    maxDamage = unitState.GetDamage().maxDamage;
    damageType = unitState.GetDamage().damageType;
    attackType = unitState.GetDamage().attackType;
}

EnemyAttack.Awake() is being called before the Initialize function from the Enemy script while unit state is still null. So the question is how to correctly initialize monobehaviour component field values if there are some fields that cannot be passed as SerializeFields or Prefabs in Editor and need to be passed down during Instantiation?

Also I don't want to initialize EnemyAttack From Enemy.Initialize function. My initial approach was to have EnemyMono that contains various properties that other scripts can use like EnemyAttack, EnemyFollowPath and so on. They just need to acquire Enemy reference with GetComponent();

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

you could try using https://docs.unity3d.com/ScriptReference/MonoBehaviour.Start.html instead Awake, should do the trick. Or handle actual initialization and "begin" execution manually.

\$\endgroup\$
4
  • \$\begingroup\$ The thing is that I subscribe to the event from the Enemy script in EnemyAttack using OnEnable so I have to get enemt in Awake function and not in Start as it runs after Awake and after OnEnable. But actually I can see that I can fetch Enemy in awake and do init staf in Start function and it works, for some reason I didn't think about that. Also I don't understand what you mean begin execution manually. \$\endgroup\$ Commented Mar 17, 2023 at 13:11
  • \$\begingroup\$ @TarasFityo it sounds like you found your own working solution - want to post it as an answer? \$\endgroup\$
    – DMGregory
    Commented Mar 17, 2023 at 13:38
  • \$\begingroup\$ Hi @DMGregory, I am not sure if that is actually the best solution, maybe there is some better approach. \$\endgroup\$ Commented Mar 17, 2023 at 13:44
  • 1
    \$\begingroup\$ That's fine, rating which answer folks think is best is what votes are for, but users can't vote on your answer until you post it. Though I'd also say the ultimate arbiter of whether a solution is good enough for your needs is whether it works in your project, and that's something you can test and prove yourself, no matter what us Internet strangers say about it. 😉 \$\endgroup\$
    – DMGregory
    Commented Mar 17, 2023 at 13:46
0
\$\begingroup\$

You can have the factory method where you instantiate the prefab in WaveManager also call Initialize on the EnemyAttack after you initialize Enemy. There you would execute the code currently in Awake. This allows you to control how you initialize these components that depend on each other and orchestrate the order in which that happens.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .