I’ve been working with blueprints for a while now, and absolutely enjoy them. However, I have run into a snag with a script I am working on. I have a grappling hook that technically works and both pulls enemies to the player and pulls the player to objects. However, once the location is reached the hook tends to go a bit awol. It will either whip the player back and forth along a wall until the player lets go or, in the case of enemies, will zip them past the player and continue on along the direction they were going until the button is released. What I am attempting to do is zero out the velocity of the player or enemy movement once they are within a specific range. I have tried comparing the length to zero as well as comparing the vectors of Hit location - player location and player location - hit location to see whether that would work, but unfortunately I haven’t been able to get any good results while running the gate open.
I was wondering if anyone had any suggestions or tips that could get this to function properly. The image above is the particular portion of the script I am testing on. Basically the gate is opened if an enemy ai is hit by a single line trace by channel. The “Enemy Pull” is a timer that continuously moves the enemy AI to the player (I use a timer to avoid using tick as I don’t want the pull to be frame dependent). Closing is just attached to the key binding as a custom event to close the gate when the key is released. In this instance, I am subtracting the hit location from the player location to get velocity on launch character. Please let me know if any further explanation is needed. Thank you!
if you substract 2 positions, they rarely are identical because of float point numeric error.( unless you set them to be identical, or entered the same)
you can have a threshold value so hook no longer pulls if distance is below that value.
the standard radius of a template pawn is something like 45, and 200 unit in height, so when you try to set threshold, keep that in mind.
if you hook on to something, temporary disable their ability to move until the gate is closed.(either you or enemy)
do this first and see if you can reduce jitter.
Thank you for your suggestion, however I’m a little confused by the threshold. I attempted to use a get vector length, and if the length of the Actor location - Player location was <= a number (I chose 45 to give my player a bit of a buffer) it would enter a launch character with a velocity of 0,0,0. However this never fires off when the pulled object gets within that <45 mark. Is there a better way to set the threshold for when to stop providing velocity?
It’s kinda hard to understand your description, can you break it down to a list of things that happens in order(ie. 1. I do this. 2.this happen. 3. I want something else happen) or maybe putting a video showing?
Ok so I’ll walk through the blueprint real quick. The first image is my keybinding setup. I have it set so that when the grappling hook key is pressed, it begins a trace, and when released it uses some custom events to close gates.
&stc=1
The trace is a trace for objects, I just set a bunch of different types in the array for testing, the main one I am concerned with is the enemy AI.
&stc=1
This goes to a cast to that checks if the object hit is a character, and if so what type. If it succeeds, launch that character towards the player by taking the Player’s location and subtracting the hit location from it every time the timer ticks. Finally, if the cast is not successful it must be one of the other objects, so I launch the player to the object by subtracting the player location from the hit location.
&stc=1
&stc=1
&stc=1
Now, TECHNICALLY this works. I’m happy with where it is I just want to clean it up a bit. The problems come in when you attempt to pull to you or pull yourself to an object. What ends up happening is the enemy object pulled to you will zip past you and keep traveling in the same direction until the g key is released. The opposite is true of the player to object. You end up rubberbanding back and forth until you release the key when you reach the object destination. I hope that makes sense! Thank you again, Penguin, your help is much appreciated.
ohh, good thing I view the thread before the screen caps are gone.
Anyway, I took a bit time replicate your graph and setup in a level blueprint.
Turns out as easy as I think but here is the hint and gotchas:
minimum distance to stop needs to be at least 2*capsule radius + something you defined(>90 units for stock character), otherwise the collision will stop them from pulling together, but you still try to pull them.
that also means if you are pulling toward a level wall, the minimum distance to stop pulling is capsule radius + something.
I use the node FInterp Ease in Out when the distance between actor and target are with in a certain range, this is really useful as you can easily decide how fast your speed drops, and you can experiment the feels before you settle with parameters.
the rest is quiet easy really, if distance > interpolation range, pull with constant speed, with in range pull with speed decided by FInterpEase in Out, once it enters minimum range, don’t pull.
I appreciate all of your help, though I’d prefer it if you didn’t post the graph just yet ;). I really like digging my heels in and trying to learn, though I think my current problem is coming from a lack of understanding as to what Finterp ease in/out does.
I feel like I am on the right track here, or at least heading that way, but what is happening is a bit interesting. I chose an arbitrary number (125) for the B value to add some additional buffer to the stop movement. When I release g then press it again it works as expected, if the enemy is not within 125 they are pulled, if they are they do not move. However if it is checking this distance while g is still pressed the forward movement does not stop. I’m going to keep digging into this, if you have any suggestions for what I am doing wrong I would be grateful!
so basic explanation of how FInterp Ease in Out works.
For linear interp, it’s fairly straight forward, you got a and b, alpha decides what’s inbetween in linear fashion.
With smooth in/out, it’s sort of a smoothstep function(I didn’t check the code so I’ll just assume here).
Like this in wikipedia: http://en.wikipedia.org/wiki/Smoothstep
So if you check the curve it has a shoulder and toe bending area, for UE4’s node, if your exp is 0, basically it’s linear interp.
If you increase exp more, the shoulder and toe will get closer and closer to the middle, to a point it might become a sudden drop in speed(say exp=10) in the middle of curve.
for your example, let’s assume that a is near and b is far, alpha is where you are currently located and return value is a speed multiplier.
You want B in a number that it’s not too far away to slow down too early, also not too close that you keep pulling when you already collided.
You exp should be in a number that still pulls you in almost to colliding distance, while making the return value small enough so when pawn enter the stopping range you won’t notice it.
That requires some experimentations, as the value varies when your speed, choice of interp range, and how fast to slow and stop range all are related.
I suggest you watch the return value of this node and then observe it to get better understanding how to tweak your parameters.
I still haven’t been able to get the Finterp to do anything unfortunately. However, I did find at least part of my solution. I was getting the hit location instead of the enemy pawn location, which was preventing the location - player location to properly update. I now have it as enemy ai actor location - player location, which does stop movement at >125 (or other number), however it isn’t smooth and has produced a bit of an interesting result when pulling the enemy from a higher z axis. If they hit you from directly underneath it flings you into the air.
you mean if your are at high ground while pulling enemy that fires at you and hit?
If you do have a radial force upon hit, then of course you will be up in the air, and if your aren’t pulling fast enough, you can both just keep going up.
It’s game logic, so you’d have to “deal with it”. Like disable enemy movement/fire if they are getting pulled, or make sure your force vector does not introduce too much Z-axis amount, etc.
For FInterp, just experiment with it with a cube or something, try a few combinations and you will get it.
I don’t have a radial force on hit with this character, but I believe it is just because the collision box gets underfoot and forces the player pawn upwards when it hits. I’m not worried about it as this was more of a “because I can” project than anything immediately important. I will keep playing with finterp and when I understand it better I may try to implement it. Thank you for all your help!