top of page
Search

Log 21: Programming Links

  • Writer: Kassandra McCormack
    Kassandra McCormack
  • Sep 29, 2024
  • 5 min read

At first I thought about doing everything in a component for the Linked Attacks, something that I could drop on a character and it would just work. The problem with that is that components can't come with their own collision volumes. So then I tried making it a separate blueprint that I could add as a child actor called BP_Linker.


The first thing I did wasn't even on the Blueprint, it was in the physics engine. Because I don't want the overlap events to be going off for everything that the character can walk past, I made a brand new Object Response physics layer, and just called it "Linkable". Now, with the collision volumes existing on only this layer and ignoring all others, they can functionally only "see" other volumes on the same layer. So with that, I could safely move on to the Begin Overlap and End Overlap events for the collision volume. At first I added/removed any overlapping actors to an array for storage, depending on which event triggered. I did this so that if characters are standing close to each other, but do not meet the requirements for linking, and then they do while still close to each other, I can send a message to all the others that things have changed and to create links. Eventually I would realize that I was just going out of my way to recreate an Event Dispatcher and just use those, but shhh, I didn't realize it yet.


Next I dropped in a Niagara component containing an arced lightning Niagara system I had created before to act as the visualization of the link. Dropping the Blueprint in as a child actor on the player character and a couple dummies, and it worked like a charm.


Except, then I ran into a problem: because BP_Linker was a child actor component I couldn't directly access the event dispatchers that I had made to interact with the actual characters. The ones that made the whole thing work at all.


So I had to scrap the BP_Linker and figure out how to convert everything into an actual component. It was more-or-less straightforward: I used regular dispatchers instead of an array of references, and I created soft references to the Niagara component and Collision volume that need to get passed into the component's Initialize function during the character's Construction script. Eventually I got it transferred over and working:

ree

Then I was left with a handful of aspects that, while they aren't shown here, needed to be built: 1) The linking should only occur between characters that have the requisite amount of Power, 2) They shouldn't be able to link through walls/floors/etc., 3) when the player leaves a character's range, that character should look to see if NPC in range can act as the bridge to link back to the character (Kind of like how they are in the gif, when the player first approaches), and 4) When the player leaves the range of NPCs linked together the NPCs should also lose the link, 5) if the wall/obstacle is no longer interfering and the characters are still in range, establish the link (and break the link if an obstacle gets in the way).


The first thing I worked on was number 2: not linking through obstacles. I did this first because I figured it would be easiest, all I would need is a line trace between the character and potential link and if the trace hit something, then don't make the link. In order for this to work, I needed to add in a parameter for the overlapped other component so I could know where to send the trace. Other than that it was relatively easy...once I remembered to send in "Other Component" from the Overlap event and not "Hit Component", silly mistake.

ree
Not only linking through an object, but bonus: NPCs stay linked even when player leaves range.
ree
Correctly not linking through obstacles

Second thing I worked on was number 4, this one I had to add on to the "Priority Changed" response function. So now, when the link to the player (whether that's the player itself or another NPC) changes their priority (such as the player leaving range) if that new priority is lower or equal to the current priority the link is canceled. This has the benefit of also delinking everyone if someone's Power level changes to be too low...once I hooked up the Power analysis as part of the code. So that's also number 1 done.


Number 5 required an additional function to add to the dispatcher called by tick, as well as keeping all the overlapped linkers in an array. Linkers are added to the array on overlap, and then the tick function goes through the array and does a line trace to them to check for obstructions. If an obstruction is detected between it and the primary link, it breaks it, or if there is no obstruction it forms the link. Before I realized it, the function also solved number 3.


Of course, nothing goes smoothly in game development. I had a couple of..."interesting" bugs pop up that had nothing to do with my Linker Component, and everything to do with some quirks of the Unreal engine that I had to work around.


The first quirk is that when you place blueprints in the world if they have different settings from their unspawned counterparts, you get a weird mix of the settings. Its difficult to describe so I think showing would be best:

ree

In this, the blueprint version both Targetable Characters have their faction set to "Player", but in the level the right hand one has it's faction set to "None". As you can see, when the player approaches both, they form links properly. And when the player approaches the left hand one, it forms a link to the right hand one properly. But when the player approaches the right hand character no link forms to the left-hand one. Fortunately this won't be too much of a problem as in the finished game everything will be spawned in and not hand placed in the level.


The second quirk...I don't know how it was even happening.

ree

Here, the line trace is hitting something. I had to put in a Print String to find out what it was hitting. It was, somehow, hitting the base that you can see far off to the right and being nowhere close to the hit indicator. I honestly don't know how it was hitting. I figured it was because the base is set to be considered "World Static" for collisions, which is one of the object types the line trace is looking for. So in order to fix it, I just set all the base meshes to be considered part of the "Destructible" layer since I wasn't using it anyway.


That's the Linker Component done. Next I moved on to making the button press for the Ultimate actually do something.

 
 
 

Comments


bottom of page