The title is probably kind of vague / confusing, but here I will explain my question better:
I have an actor called “Soul Generator.”
The Soul Generator actor has a variable called “soul count”, which is an integer with the value of 1.
In the Game Instance, there is a variable called “soul POINTS”, which is an integer, default value of 0.
When the player stands on a Soul Generator and presses “E”, it is supposed to increase the “soul POINTS” in the Game Instance by 1, and decrease the “soul count” in the Soul Generator by 1, thus transferring the soul from the Soul Generator to the player (Game Instance).
This works correctly, however problems ensue when I have more than one Soul Generator. I want it so that when the player presses “E” on a Soul Generator, it will transfer the soul from the Soul Generator to the player, but only for that particular Soul Generator. Currently, it will transfer the soul from ALL Soul Generators to the player (Game Instance).
How do I make it so it only transfers the soul from the SPECIFIC Soul Generator that the player is standing on, and not ALL Soul Generators?
Here is what I am trying to work with, if it helps add any context. Hopefully my question is understandable, and thank you for reading this short novel of a question and thanks for any input, it is greatly appreciated.
When I press E, I set a variable called “isHarvestingSoul” to true in GameInstance. When released, it sets it to false.
In the Soul Generator blueprint, I have that if the player is standing within the hitbox of the Soul Generator, it says a variable called “isInsideSoulGeneratorHitbox” to true.
In the Soul Generator’s Event Tick, I have that if isInsideSoulGeneratorHitbox is true AND isHarvestingSoul is true, then it will do the transfer.
Here’s a picture of the blueprint, I think itll be very helpful
Without thinking too deeply inside the issue, perhaps you may need a different variable for each “Soul Generator” as it doesn’t have a way to differentiate between them when decrementing.
Ah, yes, I can see exactly why this is happening. You have state mixing going on. Let’s gut this and make a slightly cleaner interaction. There’s no need for the game instance to be involved with the interaction beyond the swapping of the souls plus we’ll be able to remove unnecessary tick activity. You’re working with an event driven mechanic so let’s do our best to keep it event based.
One approach would be the following…
Let’s reverse the overlap and have the overlap reside in the character.
Off of “ActorBeginOverlap” (in the character) check to make sure the actor is a soul generator. If it is then save it to a variable (the actor that is)…if not then clear the variable (just an empty call to set).
Off of “ActorEndOverlap” (in the character) simply clear the soul generator variable (just an empty call to set)
Now, when the player presses E, it looks to see if the soul generator variable is valid. If it is then it calls a function like “TransferSouls”.
The “TransferSouls” function can be a function within the soul generator that then proceeds to take a soul away from itself and add it to the game instance count.
Make sense? This gets rid of the needless on tick functionality plus the dual state issue.
These “Soul Generators” are things that the player buys and can spawn, like the point of the game is to keep buying and upgrading them, and have as many as possible. They don’t actually just have one soul point, they generate them over time, I was just using the one soul point as an example.
If you have multiple soul generators, which one having independent soul counts, you want to create a variable type “map” and use a “save-load level state” logic in order to track all soul generators in your game. Each soul generator needs to have a unique ID, and it is an advanced workflow, but it will work if done correctly.
This is the official tutorial from Epic Games that covers save-load level state. It also comes with a sample project for download. Then, you still need to become familiar with variables type “map”, which require more logic to update/retrieve information.
This does kind of make sense, I will try and work on something like this. I agree that the EventTick is not necessary, I am pretty new to UE4 though so I’m just working with the smaller set of things that I know, if that makes sense. In step 2, what do you mean by saving the actor to a variable? What kind of variable can I store an actor in, and what does that mean?
Regardless, thank you for your time spent on helping me, is much appreciated!
No worries, it’s a journey for sure so I get that you’re working with what you have.
You can store just about anything in a variable. A quick way to do this would be to drag off of the pin in question. When you release, a context menu will pop-up. At the very top of that context menu there will be an option called “Promote to variable” or something along those lines. Select that and it will automatically create the variable of the right type for you.
In your case specifically I would cast the “Other Actor” to your soul generator class. Then pull off of the output pin from that cast to create your variable. Then just name it to something meaningful to you like “OverlappingGenerator”.
EDIT: Just to be clear, from a logic perspective you want to make sure that if the character is not overlapping a soul generator then the new variable is “empty”. That way when you press E and the character checks to see if it’s valid, it won’t be and the character will know that it’s not overlapping a soul generator at the moment. In order to do that with an actor reference variable you simply need to call the set function of that variable without a parameter.
For step 2 on your other reply, you said:
“Off of “ActorBeginOverlap” (in the character) check to make sure the actor is a soul generator. If it is then save it to a variable (the actor that is)…if not then clear the variable (just an empty call to set).”
This is what I have so far. I am able to save the Soul Generator actor to the variable, but how would I clear the variable if the actor is not a Soul Generator? (There are going to be different types of Soul Generators, this specific one I’m tryring to do is called “Pile_of_bones.”
Would it be off of the “Cast Failed?” or something else? Also, how would I account for multiple types of Soul Generators, would that also be from Cast Failed? I’ve always just ignored “Cast Failed” up until now.
Rereading, I know that to clear the variable, I just use, as you said “an empty call to set.” This makes sense. I guess my only question from this reply is that, would I do that off of the Cast Failed? Thank you again
Not to speak too soon, but I appear to have solved my problem using your steps, combined with a tiny bit of my own little “uhh this works i guess” stuff!
Thank you dearly for the time you spent helping me, it is greatly appreciated. Hopefully I will not be coming back in like 10 minutes realizing everything isn’t actually solved.
Yeah, cast failed as that implies that whatever actor you’re overlapping with is not a soul generator. Same goes for off of ActorEndOverlap, just an empty set.
So this gets into a broader topic of best practices. You can always brute force it and simply add a cast to your other soul generator(s) off of cast failed until you’ve exhausted all of your potential generator types. The issue of course is maintainability. As you add or take away generator types you’ll always have the need to update that section of code. For a project potentially small like this, it might not be a big deal but as you start to take on larger projects it can be a nightmare. If I were implementing this I would likely do it with a base soul generator class. All common functionality would be placed in that class and then you can sub-class from the base in order to create your different generator types, placing any generator specific logic for the given type in its own class. You would then end up with a single cast like you have above but it would be a cast to your base generator class. That would act as a catch-all where you don’t care what kind of generator you’re overlapping with, just that it’s a generator period.
…like always, a couple of ways to approach that scenario.
Yeah, I think for this project, I’ll do the brute force stacking of the Cast Failed. I only plan to have <5 types of Soul Generators. I definitely do see and agree with you on maintainability being a big problem for bigger projects, specifically if I had a TON of different Soul Generators.