So UE4 treats an analogue stick’s output as two float values passed through every Tick, on two separate execution paths.
What I need to know is the vector of the analogue stick, every Tick, and it must be PRECISE.
Now, generating a vector from two floats, that’s obviously no problem; a simple MakeVector node handles it perfectly. The issue becomes the order in which the values update.
For example, suppose I take the execution paths of both of the InputAxis execution events, merge them together, and print the value of the vector they make.
If I push the stick at a 45° angle, I should see a series of 0° values, and then a series of 45° values. In fact, what I sometimes see is a single 90° value and THEN a bunch of 45° values; obviously what’s happening is that the first InputAxis event is firing, pulling its value this tick, and (since the other event hasn’t fired yet) making a vector from its new value and the other vector’s OLD value.
What I need is a way to make sure these events wait for each other; I need to know that, when I update the vector value, BOTH InputAxis events have had a chance to update their values for this frame. But I don’t really know for sure which one is going to update first, it seems.
Hello,
I would try (only an idea on the fly) to use bools to check if other event is done and set values to use only when bools are true, but as tick is involved, i am not sure about the best way to set. If you could illustrate more what you need, what you ever have, i could give some tries here to help find a solution.
Well, whenever you map an input axis two functions are generated. The input axis event and the get axis value function which allows you to obtain the axis value anywhere. You can use that one in the tick and you would obtain both values at the same time
Nodes 1 and 2 are the InputAxis events. At node 3 there’s a collapsed graph which takes those two floats and makes a unit normal vector (it’s collapsed to save space, but what it does is it creates an XY vector from the two values, then gets its length, and if that length is less than 0.85 it uses a vector of 0,0,0 and otherwise feeds out the in vector with its length clamped to 1, to the “Input Vector Sequence” pin. The idea here is that, when pressing multiple stick directions in sequence, a press won’t register unless it’s a nearly-full press (for movement we use a different approach to allow more responsive input, but I don’t want slight nudges of the stick to register as “pressing left” when checking input strings). At node 4, we pass that value on to a custom event which feeds my Input String checker.
Here, node 1 is the function we’re passing the original value to (there’s a custom event on the main graph which feeds the value directly through; I’m skipping that portion of the graph since it does some other stuff unrelated to this, and then calls this function). At node 2, we check to make sure there’s an actual press (i.e. non-null value) and, if there is, we check (at node 3) our array of “input directions” to see if it’s empty. The first time we press the stick, it IS, so we move to node 4, which sets a “Master Direction Value”. This direction value is incredibly important and is the cause of my troubles.
Here, node 1 is the same as node 4 from the last image. Next, we go to node 2, which adds a direction value of “0” to the Directions array. What we’re doing, effectively, is treating THIS EXACT INPUT VECTOR ANGLE AS BEING 0 DEGREES. The reason for this is that the actor will rotate to face this direction, so it needs to count as “forward”. Then, at 3, we call a timer which will clear this directions array eventually.
Then, every subsequent tick while the timer has yet to clear the array, we call the input vector value again. We compare it (node 4) to the Master Direction value, i.e. the vector which we have temporarily assigned a value of 0 Degrees. We get the signed angle difference between these two vectors (using ATan2D and a couple other nodes inside a function) and then we quantize it to 45-degree steps. If the (quantized) vector has changed by 45 degrees compared to the last angle added, we add that new angle to the input string array, reset the timer, and repeat the process.
Now what my problem is, is that when I FIRST press the stick, and this function gets called, it needs to know the Input Vector PRECISELY to set that “Master Direction Value”. However, if the function is called by one InputAxis event BEFORE THE OTHER HAS HAD A CHANCE TO UPDATE, then when the stick goes from null to, say, up-right a 45 degree angle, what happens is that for this function call, the Blueprint is told “the Master Direction value is straight forward”, since it has the new “stick being pushed up” value but NOT the new “stick being pushed right” value. So it sets the Master Direction Value to 1,0,0. Then, next tick, it has the new updated vector, and says “oh, okay, now the Input Vector is 45 degrees different from the original, so register it”. Of course, the stick value hasn’t actually CHANGED (or rather, not enough to register as a new direction in 8-way-quantized terms), but because the function was called before BOTH InputAxis events had a chance to report updated values, so it works with incorrect information.
What I need is a way to “hold off” this function EXACTLY long enough for both functions to report their values for this frame. I could do that if I had a guarantee that the InputAxis stack was processed in some certain order (i.e. the first one in your inputs list always fires its execution path before the second) but I can’t actually find this information, and to be honest I’m not entirely sure that there’s any sort of guaranteed consistency to start with. Which, admittedly, doesn’t matter for 99.972% of cases. I tried putting a delay node before the execution of this function, and it does sort of work, except the problem is that then too-fast input changes don’t always get caught. It becomes possible to tap the stick forward twice and have it register in the input checker as a single forward press because the two hits happened so close together that the delay node didn’t see the change between loops. And further, I’m concerned that in a variable-frame-rate environment, this sort of timer-buffer wouldn’t work anyway, as sometimes it would be too slow to catch changes and other times too fast to do its job properly.
@DissonanceInt: The problem is that a GetAxisValue function is pure, i.e. unaffected by the execution path. If MoveForward updates before MoveRight, and I call MoveRight’s value from the MoveForward path, won’t it just pull the last known value from MoveForward, rather than the one it’s ABOUT to generate this frame? Pure Getter functions usually operate this way; if I call a Get node on a variable from one execution path, it calls the value known RIGHT NOW, rather than the value that it will be when another execution path finishes executing. So it brings me back to my original problem, which is determining with consistency which InputAxis event will fire first so I can always ask for the vector value in the execution path of the SECOND one.
This reminds me a bit the trouble i had with doing a game pause and solution i found was to set float variables in different tick events and use them all in event tick. So i would propose to set a var for each inputaxis and to get them in event tick and use them as you did, even with a 0.1 or less delay to not have over ticking. Then you would have your exact values.