Best way to apply multiple penalties?


my nodes are affected by multiple GraphUpdateObjects. E.g. every unit has one, that adds a high penalty to the next node it is going to, and removes this penalty from the node it just came from.
I have elevators that add penalty to their surrounding nodes depending on how long it takes until the elevator gets there again.

Now I’m running into the problem that they override each other’s effects. What’s the best way to have stacking penalties?
Preferably I’d just have a list of effects on a node and base the penalty on the sum of that.

Also, is there a good way to notify seekers when the penalties of their paths change so they can reroute if appropriate?

Why not simply add a penalty instead of setting it.
mynode.penalty += 5000; //---- mynode.penalty -= 5000;
Instead of
mynode.penalty = 5000; //---- mynode.penalty = 5000;

I was afraid that this is quite error prone, especially when objects get destroyed and such, but yeah, it’s probably tons more efficient than storing a list of effects with every node.

Is there some sort of mechanism to notify seekers that the cost of their path changed, so they can reroute if necessary?

If you make sure you are consistent with how much penalty you apply, and you make sure you remove the penalty in all cases it should (OnDestroy, OnEffectStops, On…), it shouldn’t be much of a problem. Penalties are integers as well, so no floating point errors here.

Sorry, there is no built in mechanism for that. But you could do something simple like holding the sum of all penalties the path traverses in a variable and then check if that has changed ever x frames or something.
long penaltySum = 0; for (int i=0;i<path.path.Count;i++) penaltySum += path.path[i].penalty;

The penalties I’m applying mostly depend on distances and the time certain things take (e.g. the elevator to arrive), so that may introduce floating point errors. But I can store the last used rounded number in a variable.
The solution for the penalty sounds like a great idea. If I just recheck that every time a unit reaches the next node it shouldn’t affect performance. The downside with this solution is that if something happens on the part of the path that the unit has already traveled, it can cause it to recalculate its path.
So probably I should first check if the total penalty of the whole path changed - if it did, get a new path. If it didn’t, calculate the penalty of the remaining path.
Next node, check if the penalty of the last remaining path has changed. If it did, get new path, if it didn’t, calculate the penalty of the remaining path.
This will require it to calculate the total twice (I see room for optimization there already), but saves it from unnecessarily recalculating the unit’s path.

If you don’t bother about using a linear amount of memory, you could store an array (reuse it to be nice towards the GC) with the summed penalties up to a specific node. That takes linear amount of time to calculate one when you get the path, and only needs to sum penalties once for every check.