I’m currently doing a game that has a drag and drop from (item) widget onto world (board game). The drag operation begins from widget blueprint and fires off the event tick at player control BP. The event tick does the following sequences:
First locating current mouse/touch position (using linetrace) and hits boardgrid actor to get boardgrid’s location
Re-adjust dragged item location to snap it to that boardgrid position.
Does many other various For…Loop functions such as checking if item is too big (out of board, then re-snap correctly), switching on grid highlights wherever the item is being snapped to while dragging.
Event Tick stops firing once the item has been placed on the board (Drop operation / Mouse release)
I’ve tried replacing it with SetTimerbyEvent/Function, but it actually caused more infinite ForLoop errors than Event Tick. Eventhough Event Tick works correctly but it was draining the CPU’s performance causing the dragging operation to lag.
Is there any other alternative way to approach this?
Hi ClockworkOcean, thanks for your reply! You are right, the ForLoop functions after Linetrace did caused the lag. My BP is quite messy though hope you dont mind
It starts with BP Interface from fired Widget by switching on Grab Mode. And at event Tick, if Grab Mode is switched on, it goes into the Grabbing & Snapping function
This Grabbing & Snapping function has few other functions inside it. First it goes into Snap Mode function, thats where the Linetrace processes and gives the board’s hit location result. If result is true, then it will set the new location for the grabbed item to be at that position.
I think the problem might be accessing my grabbed item block piece. I have grabbable blocks which are like Tetris shape, and each piece is serialised as ABCD. So the ForLoop function checks for each ABCD piece location whether it is out of bounds (from the bound) and re-snaps back to the correct board positions. Below is a video what I’m trying to do. You can also notice the frame rate
I think I can adapt this for the grid board snapping
Just a question though, does the ‘Get Hit Result under Cursor For Objects’ work for Touch inputs? Because I’m currently substituting the mouse as touch input under player controller settings.
The logic for ABCD pieces is the troubling part for me, because I needed to run ForLoop process for it (ie. From Piece A to Piece D), check what is it’s location, at every tick frame.
Each block that are spawned, it will be rotated randomly, therefore it needs to go through ForLoop functions. Sometimes, it spawns 2 or 3 pieces (AB or ABC) at random iterations, so I can’t really hardcode it to smoothen the performance.
And while the ‘snapping to board’ logic is workable, the block piece shall also snapped to the other already placed blocks on the board. I applied the logic of having invisible meshplanes on each ABCD piece, and the linetrace will detect on which plane it hits (eg. it hits the top part of piece A) from which it will then snap it on the location above that plane.
I’m just not sure if those logic I applied above were causing it to slow down its performance.
The Block Data Array Index which shows ‘0’ indicates for piece A. (1=B, 2=C, 3=D). I will run ForLoop function to access each piece information.
And then it will compare its location to the Board Grid data location, (eg. is Piece C out of bounds?) or is it clashing with another piece on the board (eg. is Piece B overlapping with another block’s piece A on the board).
Yes, I did apply the ForLoop with Break functions and return node to do this checking process. Not sure if this MANY ForLoop functions was the cause
When positioning pieces, use world coordinates at the last moment, just to physically place the piece. The rest of the time use ‘snapped’ locations like 0,4,7 or 5,0,3. Much easier to compare.
Each time you move a piece, set it up so that all the other pieces bind to a dispatcher in the piece you’re moving. Then, as you move it, each segment dispatches its snapped location.
This will cause all the other pieces to check their location, but only report back if relevant. If they report back, you know the piece is not positioned correctly.
If you’re going to have a tower 300 pieces high, you will need to exclude pieces based on distance, otherwise it will still slow down.
I’ll make a mock up of it.
Also, using snapped coords, it’s much easier to know if a piece is outside the board, because one of its coords will be negative.
In other words, when this dispatcher is called, the function ‘segment at position’ looks to see if any of this BPs segments are in that position. If they are, we put ourselves as the blocking actor.
Then we have the code to check if we can place a piece
We ask the dispatcher to send a signal to all pieces. If, after that, there is no blocking piece or it’s us, we can place.
A few notes
We could temporarily disconnect from the dispatcher to avoid our own position checking code being called. Then we also don’t need to check if we are the blocking actor, and it would be more efficient.
I assume that this will work in one tick. IE, the ‘blocked by’ actor will be set by the time we check it. You’d need to test that.
I don’t know how to make a dispatch not call by reference, which is what’s giving the blue NOTEs under the nodes.
Anyway, this is the general concept. Does it make any sense?
I get that the whole idea is to try avoid using ForLoops and reduce checks at every tick frame as much as possible. What I learned most from your sharing is that I think checking XYZ from a grid data manager to get its coordinate can be done via math calculation alone, because I actually used ForLoop to scan through the grid data array.
Will need to spend a few weeks to re-structure my code again and will let you know by then if it works or not. Cheers and really appreciate your help!
PS. I’m just a hobbyist developer, got a full time job)
Even with this method, every other piece will check all of it’s segments every time you propose a new position. ( That’s another way to cut it down a lot actually, don’t check or move on tick, only bother when the new coord has changed ).
Another great way to avoid unnecessary checking, is to not bother if piece A is further than a certain distance from piece B. This would only apply once you get into 10’s of pieces.
In your vid you only have 2 pieces, and it’s stuttering pretty badly. Even if you’re checking everything on tick, it wouldn’t do that for 2 pieces. That’s why I think there might be something up with your logic…
Is it possible to try Event OnComponent Begin/End Overlap for the Grid highlights? When it ‘touches’ or ‘overlaps’ with the moving pieces, it will do both re-snapping its positions and performs the highlighting function?
No worries. Trouble is, something I try and do, is stay in the mindset of the person I’m trying to help, because it’s not very helpful to say ‘hey, just totally change your approach’.