Hold E to Drink/Eat

Hello, im currently asking about how I might make a Drinking/Eating system similar to the one found in the video below. Ive tried making it myself, but I keep running into issues. Any advice/guidance would be great here. Thanks!

Hi!

Is there anything you crafted already? If so you can show them even there is problems about system (input, detection, cancellation, animation, positioning). Community can offer architecture, advice or pin point bugs.

If you are looking for just overall advice to crafting an interaction system we can give, there are some already forum topics, there is one that I did a while ago and many video tutorials on Youtube.

In the blueprint of the actor you want to drink/eat, you can add a collision box or mesh and scroll down to find the OnComponentBeginOverlap, and click the + to make an event for when it overlaps. You can then have it cast to your player character and set a bool variable(For example, CanEat or CanDrink.)

Then, in the character blueprint, when you press E add branches for your variable(s) and have your eating and drinking code.

2 Likes

Well ive removed all of my former code to create it in a more stable way for what im trying to achieve.

I made a separate volume actor that I can put along the edges of lakes, rivers, etc.
My issue is that im trying to make it so, I can hold E, and it will actually trigger an event During the hold time.

Often so far, every tutorial ive found. Just makes it so after you hold it for a certain amount of time, the trigger fires. Which is not what im trying to achieve :slight_smile:

I have it also set up, so that once they enter said volume it changes a variable within the Character BP, to can_drink=True

Ill show with images below :slight_smile:

I undertand, you can always shortcut things, however its important to create them in a certain way so it becomes easier to maintain, build, change in the future, even though its a prototype.

So I will demo a prototype that is not AAA+ but something that is fair enough.

1- Putting a collision mesh every food item, every drinkable source, every river edge work however it is not the nice way to approach problem. Why? besides maintaining debugging, first of all you will spend considerable amount of time adding those to your open world game. Debugging, fixing etc. Rather than EdibleSource->DetectsPlayer let’s go with Player->DetectsEdibleSource

Made a a huge sphere collider on my character, since this a dinasour would be big anyway. Set collision to overlapp all, generate events.

Implemented th overlap event only for now and make the following logic. If Actor or Actor’s any of the components with a tag “Edible” exists then we are in the state of eating which we promote to a variable “CurrentLastOverlappedInteraction”. I didn’t distinguish multiple actors for now just the sake of tutorial. Dinasour overlaps something , last overlap is served.

2- Quickly put a test environment. Made a pool of water and make another Item_BP actor. On the spline component of lake (water body) added tag “Edible”

3- Test Actor, quickly put a static mesh and created some variables.
Event OnEdibleState : Its event with a bool. If bool true its eatable we store bEdible add tag to actor if not we remove tags.

SourceCount : We can have a source count just to start with, made an integer 10.

Event Consume : When consume called, it decreases source count, prints it, if source is zero print depletion for now and check if we should destroy this after depletion. If so destroy else, we change edible status. Additonally set a text render to source count so we can see count of items for debug reasons, this can be on your UI or something else ofc.

4- Consuming Over Time : A mentioned can be many approaches but I understand what you mean, you don’t actually want a timer as a “cooldown” but actually an actuation method of interaction. In other words : We change Interaction NoCD->Interact to StartInteract->Accumulate->ExecuteInteract , which is the correct method of thinking in some cases, It’s a much more better UX so you are right to ask around it. It’s like you start drinking but you actually drank after. You start chopping tree but bark falls after a while.

So in this, in put which triggers alltime on hold, we get trigger seconds and check agains a consume threshold (multiplied by scale). So 1st press nothing happens, waits till reaches threshold (2 seconds I put x 1 scalar). After reaching this executes to try consume and immidiately increases scalar so its on frame once.
Now it waits the 2xConsumeThreshold which is 4 seconds and this continues. Player lets go starts from accumulating from zero meaning if you start stop always under threshold nothing will execute.

After this we get the interaction if any, cast item bp and call event onconsume. If not cast then maybe its something else like lake (endless water)
OnConsume if valid we call item consume so it decreases does its job.
Else if not valid (something else) maybe you do something else over there.

Intentionally left these parts of design open for you but wanted to also show that in order to consume something you don’t actually need to put a collision everywhere. Ofcourse this can be pushed further like item descriptions, additional states enums on item base, more events, making this GAS oriented, correctly detecting what player is looking etc. also on OverlapEnd events. Intentionally made it brief but showing the fundamentals.

Let me know if this makes sense and you have some takeaways.

2 Likes

I will give this a try! And see what I can make of it :slight_smile: Ill keep you updated shortly!

1 Like

Howdy!

So Ive reviewed your system, and I really like how it works to be honest. This seems alot more reasonable than the approach I was going to take!

Now as usual, because I am not super experienced. I seem to have run into some kind of issue :laughing:

When I do walk up to the object to actually begin consuming. It detects it, however Holding E nothing happens forward onto that, And the source count doenst change.
Might it be because I have my enhanced input action to Hold?
And could you point out anything in particular that Id want to check to see where I went wrong? :slight_smile:

That’s great ofcourse there should be many additions to it but the fundamentals are there.

The input yes in this setup should be triggered all times also down to get trigger time

That should make the system work already.

However I also went one, two step further in terms of this system. I generally took a different approach(es) in different context depending on scale, usage and so on however on this one I would like to take another approach and fully centralize the logic.

In other words, Interactions can differ in many games and type of interactions. Sometimes interaction information and states of interaction can vary that we have to hold the information on the interacted side. Like interacted can have many states : Inactive, Active, Disabled, Depleted in addition to further logic of disabling, removing, adding. In your case we can make a more data driven design I feel and hold the information fully on interactor side. So I will do that a bit without going too deep if you like you can have takeaways ofcourse its your choice since its your game and you only know the end results desired.

Iteration Steps - Optional

1-I changed the input to pressed released so will start building on single event times. This is important since even though in systems level we won’t to currency/ state changes we will still need to understand player is doing something. Like started eating or chopping so we can tell necessary systems to play some animation or do something else.

2- Made an interaction component so we can plug this to other players/pawns too. Added to player pawn. Why it encapsultes the logic, its more tidy, implementable to other pawns etc. Also easier to do networking logic on encapsulated code.

And created the scanner collision sphere with a function, which simply makes a detection sphere.

3-Created a new function as UpdateScanner. This simply gets all actors around if they match tag and they are not already discovered they are added to an array. Didn’t use OnOverlapBegin and End since by nature if they overlap with something already wont trigger and would need logic, so rather than we go more granular and detect them with a rate. Also on loop complete we call an OnScannerUpdated event. Also exposed tag for easy change from component. This is a trade off bringing more depth to code but more stable in longer tern.

We run this function with loop in begin play. You can set a rate and expose variable, a lower rate is better performance but not a big one generally.

4- Now we know the interactions around but maybe dino moves farther etc so maybe its not relevant but not removed from array. So will make another function to EvaluateInteractions which we can do many things inside.
Made EvaluateInteractions and bind it to OnScannerUpdateEvent

Inside created some local variables.
CurrentClosestDistance = Which can maximum scanner distance at the beginning.

We loop through the current interactions array, and get a distance of the actor “CurrentEvaluatedDistance” If this object is not valid or outside of the minimum distance we remove from array cause its not relevant anymore.

We check against the current closest distance if its smaller than we designate this as the CurrentInteractionCandidate and set Closest distance to that actor distance. So next item if closer we will evaluate that its more relavant. So closest actor wins. Since this is a dino maybe direction not that important, could be though.

After loop complete I set a global Current interaction just in case , call an event newly created as OnInteractionChanged. This calls even its empty (no interactions) since this would be quite handy on the UI side or on other systems to talk with Interactions. Show Hide UI etc.

You can assign a log and test in the event graph

5- Created and enumaration with some states. It is important to seperate states of what interaction is doing vs what player is trying to do, so we will use this states with that manner.

6 - Created a blueprint Interface BPI_Interactions, Just added a single function for now.

Also added the interface to my component

7- Getting Inputs

Created a new custom event inside component as TryInteract with a bool. I want to interact or not.

This branches into a new function as SetInteractionState, True ->Started and False->Stopped

Inside this function is quite simple, we get the enum that we created as input, switch
Start ->CreateAtimer with Threshold (Wait Time for each execution)
Stop ->Stops This Timer

Additional event created with the enum to inform anything about the state “OnInteractionState”
this is quite handy to bind animations etc. Drink Start, Drinking, Drink End etc. Ofcourse that time for different interactions we need to know what we are interacting with which requires data transfer however can be implemented further into this system if wanted.

This timer in a loop will always call an event “RequesInteractionExecution”. We hold timer since we have to stop it also other dependencies in future can need to access this timer to sync UI feedbacks or even animation / vfx / audio feedbacks.

Which executes the same function with Executed enum state

Since its pure BP we have to do like this or similar loop, since we cannot pass a true delegate with blueprints. So when player always holding the button timer will always loop back to Executed branch and call HandleExecution

In the BP whatever input we have we can redirect inputs now like this

8- Executing Interaction

When we hold button for a while timer executes function HandleExecution and this simply gets current interaction, looks for an interface we created and message DoInteraction

If this doesn’t have an interface, you can resolve individual classes to do something. I left these places open ended again. Can be a dictionary , can be a InteractedComponent on the actor to do things, which is the preffered method for me in most cases.

9- Item Base and Setting What Interaction Does

I changed nothing over here. It just listens interface DoInteraction event and the rest of the logic is on the Item Actor side we don’t talk with it anymore.

If wanted you can push information from Item actor to Interaction Component via interface also.

No casting, no deep coupling but a working system that is extendable, changable, debugable and furthermore lowcost. It’s a prototype, no networking, no state, no big data communication in between but can be done if wanted.

Overall component at this stage should be something like this with exposed variables

Let me know.

1 Like

AWESOME!! Thank you so much, Ill start working on this and ill let you know of any issues I may run into. You have no idea how much I appreciate this kind of dedication to help me, Thank you so much!

-ps
Sorry I didnt get back to you sooner, Ive been working very hard these last few weeks, so its sometimes difficult on my memory :grin:

1 Like

Howdy my friend! So last night I was working on replicating the examples you showed me, but I ran into a problem. More specifically making this node here in my function to create the scanner,
I couldnt find this node for the life of me. Are you able to let me know what its called! Thanks :slight_smile:

Its AddComponentByClass

1 Like

Ohh thank you my friend! :heart:

And just to clarify, I should be removing all of this original code here correct?

To then replace with our newly created system as shown here?

Let me know! :slight_smile:

Yes exactly

Hi my friend! So I replicated everything seen here, however when I try to actually hold E to interact. I get no return, I threw a breakpoint on the Try interact node as you will see in the image, however when I hold E. Nothing returns, any idea as too why? And what I might want to check to find errors?

Hi there try putting on started since we don’t have to be super rapid with input over here.

However you can change settings and remove pressed or change with down to get inputs on trigger. It should execute as well.

Hi, I figured out my issue. It was user error on my part haha, I had accidentally used the wrong Input action type, Now I am trying to test the consumption on the actor ive set up. And I walk up to it hold e, and the number does not change. So I assume it has to do with my setup for the edible actor?

Below is my nodes I created according to your advice,

Could it be because my Boolean for BisEdible, is set to False as default?

So lets make sure you receiving the event at the actor first. You can put a print “hello” to beginning of event to see if you are receiving or you can aswell use a breakpoint.

if you are not receiving the event, then make sure the tag you check is the same tag in actor and test again if actor receives event.

If not there should be a problem in the back somewhere. Suggest first going to near an actor and making sure the actor evaluated as interactable correctly.

And Yes make bIsEdible true so it add the tag.

Hey! I tested around, and I put a breakpoint on Event_DoInteraction
And the breakpoint didnt activate. I believe the actor itself isnt being recognized,

Did you do this one?

When you get close its printing correct interaction name?

No : Then something wrong in your Create Scanner, UpdateScanner logic.

Yes : Then check your request is coming correctly from the input into

So whenever I get near it I actually get nothing printing off, so it must be something around there