top of page
Search

Log 26: Something's Off with Locking Off

  • Writer: Kassandra McCormack
    Kassandra McCormack
  • Feb 2
  • 4 min read

This is going to be a short one. Work was really tough the past month and left me feeling too drained to do any extra work, but I got some stuff done.


While finishing up testing on my minimaps and map markers, I discovered that if the player is locked on to an enemy and the enemy dies, the lock on persists even after the enemy is destroyed.


The first thing I did when trying to fix this was converting all my hard interface references to hard actor references and message calling the interface methods. I did this because it is not possible to check if a hard interface reference is "valid" or "exists", but it can be done with actor references. My figuring was that if I do a validity check and it comes back false I can cancel the lock. It sadly didn't work so I had to try something else.


The next thing I tried was binding function calls to the character's death dispatcher. Admittedly this should have already been in place. This one was fairly straight forward...except for the fact that it didn't work. And when I went back into the code I realized I had accidentally built an infinite loop and it should have crashed the game, but that didn't happen either. Which was concerning because it meant a function wasn't getting called somewhere.


After scratching my head for a while, I finally decided to scrap the whole thing and rebuild the lock-on system from almost the ground up. The first thing I realized was that I could simplify the whole system by only making 1 component that only went on playable characters; instead of a component for playable characters and a component for AI characters, all inheriting from a base lock on component class. Because locking on is solely for the convenience of human players to keep track of a target in a group, I can offload any of that that the AI needs to do into the actual AI Behavior Tree controls.


One thing I tried to do was replace my Trace for Objects with Trace by Channel. I wanted to try this because I could set up the Channel trace to only look for objects that I put on a special lock on channel, mostly so the trace would return fewer things that have to be looped through. Unfortunately I couldn't get the Multi Sphere Trace by Channel to actually hit anything, despite setting everything up. After troubleshooting for a while I decided to go back to tracing for objects, because I wasn't feeling well and just needed to progress and sometimes "good enough" is good enough. Fortunately I repurposed an unused Object Type I had made before to be "Targetable" and then any primitive component could be locked on to, which means I didn't need the specific Targetable Component that I had made before.


Once I got the trace working, I had to parse the hits. The first two things needed to check are if the potential target is of an enemy faction and if it is alive, so I needed to take advantage of the ITargetable interface that I had made before to get those values.


The next thing to check was if the potential target is actually in range, because of the way the radius of the sphere trace actually extends the trace past where I want it to be and additional check is needed. Next is making sure there aren't static objects (such as walls, floors, ceilings, etc.) in the way blocking the view of the target. And then finally, after getting through all that, get the potential target closest to the center of the screen. By making all those checks (except the center check) into macros and functions I was able to easily set up to do them every tick and if something returns false I can easily lock off.


As a side note for the check of if there are walls in the way, I put in a grace timer so if a wall passes between the player and the target only briefly I didn't want to break the lock on. I did this by setting up a timer that gets canceled if the check returns false before it goes off.


While I was rebuilding my lock on, I had looked up a tutorial for how to move a widget on the screen overtop of an object in the world. I wanted to do this because using a Widget Component requires that I cast to it in the initialization of the character in order to change the icon image (which I want to be changeable based on the player character as a nice bit of juice). Unfortunately, the tutorial I was using was outdated and no longer functioned as advertised. So instead of needlessly wrestling with moving a widget on the screen, I just used a Widget Component and cast it. Of course the widget component path means that I can't do multiple player characters locking on to the same enemy with different lock on indicators, but I'll have to kick that can down the proverbial road until I do a game with multiplayer.

Lock on indicator helpfully circled in blue

This post was a bit light on progress, but the next one will be much more substantial.

 
 
 

Comments


bottom of page