I’ve been on the struggle bus for a few days now an finally breaking down to ask for help.
I’m pretty new to this, seems I only know enough to get myself into trouble.
My setup is a Player Controller, and a Character w/ a Actor Component set up to handle interactions via line trace.
I have an Interface as well for the interactables.
In the interface I have declared functions for interact, BeginFocus, EndFocus
In the Actor Component (attached to the character) I have a Line trace set up.
The idea was if the line trace hits a interactable it’ll display widget w/ the interactable’s name and Interaction type and/or context menu (Haven’t made it that far yet)
But I’m currently stuck on getting the interaction to work, thus far I’ve only managed to either A) Crash the editor, or B) Nothing at all.
The interaction implementation is in the actor component and the input is handled on the PlayerController. its my assumption that when it’s crashed I’ve tried to execute something improperly and when it hasn’t done anything its because its returned null.
If someone could help save my bacon and point me in the right direction it’d be much appreciated.
Debuggers are extremely useful
Start from the top by setting a breakpoint in the “place” you expect your interaction logic to start, so probably AEBG_CharacterControllerBase::Interaction(). Check the values of surrounding variables (for example, are the pointers the code is about to use invalid?). If yes, you’ve possibly found a clue to the issue. If not, keep stepping into functions (for example, Interaction() calls Interact_Implementation(), just step into it and keep checking variables) until you find something strange. Report back to us if you find anything unclear.
Don’t guess, write code with intent
Both debugging (from your side) and trying to understand the code (from our side) is made harder if the code contains unused or misleading logic. A few examples:
Curly brackets are extremely important when executing logic, while whitespaces (at least in C++) aren’t. However, whitespaces (spaces, newlines, tabs) can significantly improve or degrade our understanding of how code is executed so take care to indent your code properly (there are also IDE settings to help you with those). If we take your snippet in ::InteractionTrace:
A short glance at this image might mislead us to believe the two “more indented” if blocks are on the same indentation “level”, when actually they aren’t! The first one “contains” the second one, and the third one is “after” the first one (simplified terminology), so the first and the third one should be equally indented.
Try to keep your local variable definitions (i.e. the first mention of the variable’s name) close to its first use location (while accounting for variables used in multiple blocks, which sometimes forces you to define variables sooner). This both lets you understand the execution flow of your code better (because you can more easily read it top to bottom without backtracking) and lets you easily eliminate unnecessary /unused logic. While I don’t see any unused logic on the first glance, there are multiple variables defined before the first scope they’re needed in, decreasing readability.
Regarding intent, don’t do things just because “you think you need to”. For example, unless I’m missing something, this snippet:
Calls IEBG_InteractionInterface::Interact_Implementation(), which (by the naming) seems to be an interface function. Seeing as you haven’t provided a snippet of that function, I’m assuming it has no implementation and is in fact empty (as interface functions usually are). Why is this here?
Help us help you
Figuring out what’s not working from partial snippets is kinda difficult, if you haven’t found the answer following the above tips, could you please:
clarify whether the current implementation crashes or just doesn’t work
if it crashes, please provide a callstack (a screenshot of the stack during the crash will do)
add the missing snippets (for example, the Begin/EndFocus implementation logic)
To be honest I think the majority of my confusion is coming how Youtube tutorials aren’t exactly the best source of information in a lot of case. I’m trying to escape tutorial hell and think for myself.
My current implementation crashes the editor (a little bit different from the screen shots provided) I had tried to clean some things up a little bit and follow some of the advice you provided.
You mention you’d wanted to see the implementation of the beginfocus, the beginfocus, endfocus and interact were declared functions in the interface and had no implementation in the .cpp file.
My understanding was you declare functions in the interface, and then create the logic in the various classes. Example: Setting up the line trace to interact, an then when executing interact, starts the logic inside the interacted-with actor.
After doing some more research however, I think what I want to do is move all of the input logic that is character specific into the character itself and not stored in the player controller. I don’t know if this will help, but in my mind it makes more sense than the way I have been attempting to do it.
This is the crash log I’m currently getting, its pretty consistent with what I’ve gotten other times as well.
Ok so I moved all my input in regards to the character from the Player controller into the Character class. I deleted all the functions post the line trace in the Actor component and took the line trace off of tick. I re-implemented it so the Character class (upon hitting the F key) fires a single line trace. If that trace hits an actor that implements the interface, it executes Interact on the interface. Set up a test actor lever switch, and it works as intended perfectly.
So now I guess I figure out how to actually implement it the way I wanted before and still have it work
e.g. Line trace on tick which when hovers over and actor and display a context menu for interaction.
Appreciate the help with debugging and insight on how to keep things cleaner/more readable. I defiantly got to look into using break points and UE_LOGs for debugging though.
A bit tricky to verify 100% without line numbers on the snippets and without having access to the gen.cpp, but after looking at the stack I’m pretty sure the crash happened because you called IEBG_InteractionInterface::Interact_Implementation() directly, which is unintended (as I’d hinted at previously). As you yourself said, interfaces are meant to declare functions for other classes to implement, so directly calling the interface implementation is a bit weird (but ok in some cases), but if the implementation doesn’t exist it’s literally wrong (and I assume UE generates a check for that call, and that’s the crash message you get). In other words, removing that one line would’ve probably fixed that crash in the old code.
You mention you’d wanted to see the implementation of the beginfocus, the beginfocus, endfocus and interact were declared functions in the interface
Yeah you were calling the function(s) somewhere within the snippets so I wasn’t sure if that’s just placeholder for when you get the starting part working, or if you had already implemented a base functionality of some sorts in the derived classes / interface and they weren’t working as you expected. From this reply I guess it’s the former, which is fine.
While I can’t directly give you the code (because I’m still fuzzy on the details of the implementation you want), I’m glad you found something that works and that is a good starting point for however you want to modify it. This is a very very good practice example to learn breakpoints on, it would immensely help you in the long term to take some time to do it right now.
Feel free to send further snippets if you need help (and if so, please include line numbers in the screenshots xD).
Essentially what I was wanted to accomplish was I wanted the line trace to run on tick. I had it set to fire at .01 so not too crazy. But it would detect interactables passively and when you hover on something it would call up a context menu that would display how you could interact with it. Example: like if it was just an item on the ground it might just say “pick up” but maybe on a door it might say “open” or “breach” so you could have multiple types of interactions with the same item.
In my mind I have a rough idea of how to accomplish it, store the hit result as a local variable an then call “execute_beginfocus” on that actor if it implements the interface.
Then id have to set up a check if the current hit result matches the stored hit result and if not, we end focus.
From there id imagine the context menu logic would then have to handle the execute_intereract.
@Kemichar Day job getting in the way of progress But good news, re-implemented the trace on tick, similar set up to what i had previously in regards to the trace, but the functions afterwards I had to figure out from the ground up. I got the begin focus to call a UE_LOG so that appears to be ready for further implementation with actual UI. Even got the Interact function to work with this set up as well too! However currently not sure how to handle the end focus. I did at one point have something set up but every time I hit the test actor, an then looked away, it’d crash the editor with “assertion failed” So I think I need to ponder on that one a little more. I feel like I’d some how have to get a reference to the previous valid trace hit to call End focus, which would essentially just be hiding UI that Begin focus called up.
Looks a bit wrong indeed, but also depends how it is set up in the actor component.
Does your interaction component also implement the interface ?
It probably shouldn’t. The interaction component is not really an interactable, it’s the one calling the interactions. You just need to route input to it, but it doesn’t need an interface here. Just a regular function.
// UEBG_InteractionComponent.cpp
void UEBG_InteractionComponent::Interact()
{
//...
// Do not call IEBG_InteractionInterface::Interact_Implementation here it makes no sense
}
// AEBG_CharacterControllerBase.cpp
void AEBG_CharacterControllerBase::Interaction()
{
// Even if you make the function BlueprintNativeEvent, and end up with an _Implementation suffix, never call it directly. Always call the base function name :
CurrentCharacter->InteractionComp->Interact();
}
@Chatouille In hindsight there were a few mistakes I was banging my head on the wall for a couple days.
The Interaction Comp used to have the interface implemented, not anymore
Removed the TScriptInterface which was holding the “Target Interactable” variable
I thought I needed the “Interact implementation” in my actor comp as well as the receiving actor, that was wrong as well. Haha Yikes, it was bad.