Chaining them hooks

(Successor to https://mossgoblin.com/2020/02/18/egg-and-chicken-in-unity/)

I got this problem again, when different component scripts compete for precedence. Always something to think about when you have multiple entities (not the technical term from dots).

In this case I was integrating the successfully prototyped hud/radar system into the main scene and I got the following situation:

The MapController (the main conductor in the scene) gets a list of points of interest (POI) to be displayed on the huds. It send them to the HudController.

It also positions the players and sends their transforms to the HudController again.

The HudController decides which of the POI are visible for each player and creates two separate POI lists and sends them to the player huds, along with the respective player transforms.

Then each hud takes care of initializing the compass of the player and displays the POI list it has.

Who Starts() first. Madness and definitely not the proper way.

We leave aside the fact that the two controllers and both the huds are component scripts and not simple C# objects. Quite the anguish, deciding it should be so. I would not have the chaining problem if I used pure C# classes for those, but building and setting up the scene turned out to be much much easier with properly exposed component scripts.

So… one Start() to rule them all! Here’s how it ended up looking:

MapController

+Start()

  • PrepPlayers()
    • Send players to HudController
  • PrepGeneralPOIList()
    • Send generalPOIList to HudController
  • HudController.Run()

HudController

+Run()

  • Send players to each player Hud
  • Split generalPOIList into two playerPOILists
  • Send one playerPOIList to each Hud
  • for each Hud: Hud.Run()

Hud

+Run()

  • Display playerPOIList

I feel weird having component scripts that have logic, but don’t have Start() hook, but.. it seems to work. I am pretty sure that’s not optimal and there are better ways to organize the action flow. But it will have to wait for some other project.

Compass

Created the proof of concept for the compass. Not a real compass, though, I mean markers along the rim of the minimap that show you the direction to different points of interest.

Finally got it to work (#working _with_angles), but an interesting bug appeared – in the test room the player is spawned directly adjacent to the object that the compass is tracking. And if you rotate, the compass displays the direction properly. However if you take as stroll (of whatever magnitude), the method for calculating the angle suddenly looses the abolity to work in the proximity of 0 ° and 180 ° – the statement that calculates the direction to the object starts behaving strangely – the angle, for some reason, avoids -20 ° to 20 ° (thereabout). The general behavior is that when the angle reaches certain low threshold (looks like 20 °, but I have to do some more testing) it jumps to the negative of the same, completely ignoring the values in between. Same in the other direction. Same for 180 degrees opposite. Whuh??

P.S. Yeah, a lead – the angle is calculated based on a simple direction spell (target_position – my_position). Apparently this fails when the angle is too small. Grid resolution?

Egg and Chicken in Unity

One thing I have managed to achieve is the ability to produce code that will most likely blow up in myface. At least in Unity.

I’ve always been a code-first type of guy and I find the timing methods (do they have an official type name?) to be troublesome. I mean ‘Awake’, ‘Start’, ‘Update’, etc. They’re fine and all, but the simple fact that they are (not)simultaneous makes me nervous. Each time you run the code you get an arbitraty order in which all Awakes are run. This is not bad in and of itself, but you have to build around it.

I know that there are elegant ways to take this into account and you can make code that (in this respect, just as in others) is beautifyl, as well as robust, but… If I can not find anyone that explains how to approach those fickle beasts Awake and Update, then I’ll have to write the book myself.

Specificity? Sure, why not:

The Awake method of my Mono class GreatManager wants to know the int PlayerStartingLife and asks the Mono class PlayerManager. However, the method public int ProvidePlayerLife() can not oblige, because the class has not had it’s awakening yet. If it was awakened first, it would be fine. But that is only the two-body problem. If you are not carefull you might end up with a nasty web of classes, each screaming – ‘Him first! Wake him first!’.

Right now I’ve employed heavy patchwork in some places – it the class is not awake, please ask him to do his awake routine, then as him to do what I need him to do. However, if I am going to init the classes on demand, what do I need the Awake for?

Do I say that the ‘Awake’ class is useless? No, of course. I’m saying that big part of using Unity is learning how to code specifically for Unity and that includes developing within some very odd contraints…

Not that I don’t like it, though. This I will crack. Soon.