Question about order of events

Hi,

I am making a chess-like game and I have a problem when trying to determine where the pieces (I call them units) are allowed to go. So in the picture below I am first setting the units location by putting it in an array, that stores the location of all units (arrow down in the pic). Then I run the code that determines for all units where they are allowed to go (units block each other when friendly, and can be attacked when hostile).
Now the problem is, this does not properly work without the delay between the two nodes in the first screenshot. So if I run this without the delay, the units location isn’t updated yet when setting the valid locations for other units. So it is just able to walk past friendly units for example. Because the delay fixes this, I’m assuming that the “Set Unit Location” is simply slower than “Set All Valid Locations”. Firstly this doesn’t make a lot of sense to me, looking at how much more code must be run to set valid locations. How can this simple “Set Array Elem” be so slow?
Secondly I need another fix for this, other than the delay. I will have a lot more units later on and I would have to fine tune this delay perfectly to work in every thinkable scenario. That’s not really doable, so I need another way of making sure that the “Set Valid Location” only runs after the “Set Unit Location” is done. I have tried all that I know of but nothing worked.

Any help is really appreciated.

In the first screenshot, are you in a loop ?
It looks like you have a single loop where, for each unit, you set its position and then define valid moves. But those moves depend on other units, which haven’t been positioned yet (because loop works item by item).

There is no slower/faster execution concerns here, everything happens in an instant frame execution sequence. It’s just the logic that is flawed. The delay fixes this “magically” because of how it’s designed which would take a while to explain, but as a result it should work just as fine even with a delay of 0.01 and shouldn’t need any fine tuning, it’ll just delay execution until next frame which is far enough to ensure the loop is done executing (= all units have been positioned).

A proper solution (without delay) would be to make two loops. Make a Foreach loop to position all elements, then, from the loop’s Completed pin, make another loop where you define their valid moves.

1 Like

Hi, firstly: Thank you very much for your answer!

Secondly: Let me clear up a few things.

So I am actually not in a loop in the first screenshot. And there are actually two different cases that have to be distinguished here. So at the start of the game, I am setting the position of every unit and then only run “Set valid locations” once. (This is not seen in my picture, and happens through a different set of nodes.) In that case I have the same problem and also have to use a delay for it to work. The second case is the one in my screenshot. This always happens after a single unit has moved, and therefore only that units location has changed, so the problem you are describing in the first paragraph shouldn’t be an issue.

About what you describe in the second paragraph: Unfortunately I tried it, and a delay of 0.01 actually doesn’t work. I think 0.1 doesn’t even work, so it does need to be set to a specific value in order to work. In the case where it is set at the start of the game, the delay actually has to be 1 second in order to work, so there has to be some kind of slower/faster execution issue imo.

I see then, my interpretation was wrong.

It sounds a bit more like a networking sync issue, are you testing in multiplayer? Which mode specifically (dedicated / listen server) ?

I see that the two replicated reliable RPCs are located in two different classes. SetUnitLocation is in POCamera(?) and SetAllValidLocations in RTController(?). It’s worth mentioning that, despite being reliable, there’s no guarantee the events will arrive in the same order here. Reliable only guarantees order within the same actor channel so you’d be better off having both events in the same class.

Anyways, you probably shouldn’t be triggering two RPCs in a row here. Why not call only SetUnitLocation(SERVER), and at the end of SetUnitLocation code, add a call to SetAllValidLocations ? This way you have only one RPC from client to server, the server updates location, then sends the multicast.

However that is not the root of the problem. I notice your array of locations is a replicated variable, while SetAllValidLocations is basically a multicast RPC, so there’s your problem. Variables are slower to replicate than RPCs because they are subject to all sorts of optimization/prioritization to smoothen networking. So without a delay, the multicast RPC is reaching clients before the replicated array. There’s no guarantee about the delay for replicating a variable so it’s not a good solution to use one.

There are two ways to go about this. You can either pass the array of locations as a parameter of the multicast RPC - or get rid of the multicast RPC entirely and enable RepNotify for the array variable. Enabling RepNotify should auto generate an event called “OnRep_UnitLocationsPO” which is triggered whenever updates are received, so it is an ideal place to recalculate valid moves.

I have tried putting “Set all valid locations” right after the set array elem node, unfortunately that didn’t help either.

But I will try your other suggestions, might take a while though. But thank you very much, also for your explanation!