seandewar / UE4BunnyhopCharacter

(August 2015) Raw code from an old UE4 project for a bunnyhopping player actor (with trimping & a Source engine stamina system)
MIT License
16 stars 7 forks source link

Question(s) about your bhop code... #1

Closed Liquidmasl closed 5 years ago

Liquidmasl commented 5 years ago

Hey man, this is probably not the right spot for such question but i am kind of desperate and i didnt find another way to contact you..

So i stumbled upon your Project and i was quite amazed by your results in the youtube videos. I thought i try to implement this using blueprints (which i do reget a little bit i have to say) but i'd like to stick with it.

I used your code as.. inspiration so to say. but it just doesn't work right. And there are a few things i dont understand.

I just try to get the bunnyhopping going for now, all the rest is work for another day (stamina, water friction, Trimping, etc).

In your CalcVelocity function there is a lot of stuff i dont comprehend right at the start. I feel able to follow again right before you apply friction, what is nescessary in this function just for BHopping? What does ApplyRequestedMove? and what is bForceMaxAccel? Also you use a Variable named "Accelerate". And i dont really understand what this value is. I thought it would maybe the the recent acceleration from the characterMovement componant, but that cant be because if its zero there is no way to actually start accelerating. Without using it, or using 1 in its place makes my Actor go.. suuper slow. it seams to be necessary, or something else in my BP is way off..

And then I thought its directly from the input, but in this case i don't understand how it can have magnitudes that differ from 1. Also where would there the difference to wishSpeed then..? Is it just for Analog controls? (where its possible to accelerate just, eG. 30% speed?)

If you have no time, motivation or just not feeling to respond I can understand, but if you do I would be highly highly thankful. Its just the start for me in unreal engine, and the next step will be code for sure, I thought BP would be easier to start out but just 3 lines of code can be a mess with blueprints...

I got a few screenshots here to, i tried to tidy them up as much as I could.

Acceleration "function": AccelAlt

Friction "Function": friction

Actor base values: valuesActor

Movement Component Values: valuesMovementComponent

Again, if you can help me out here, or maybe just parts of my question, or whatever, i would be really grateful!

Greetings from Vienna, thanks for the awesome Project! Marcel

Edit: I did not do anything to prevent friction from kicking it yet, so I know BHopping would not work yet, but i tried to get the basics down first, like.. walking normally

seandewar commented 5 years ago

Hi Marcel,

Thanks for contacting me -- I'm happy to see this project is still attracting interest!

Unfortunately, I haven't tinkered with the Unreal Engine for a few years and my current situation doesn't allow me the time to really revisit it anytime soon; as such I will only be able to answer these two code-related questions:

In your CalcVelocity function there is a lot of stuff i dont comprehend right at the start

Some of the code in this function is taken from UCharacterMovementComponent::CalcVelocity's source code and is used to enable path following (i.e pre-defined character cutscene movement). I wasn't interested in inheriting any of Unreal's movement logic with the path following functionality, so overriding and calling the base method wasn't an option. If you're not interested in path following, you can forget about stuff like ApplyRequestedMove and bForceMaxAccel.

I think only these lines are strictly relevant for what you want:

// NOTE Restore the last movement mode so that friction and accel uses falling / jumping values
// for at least one extra frame so that bunnyhopping works without "jerking" as soon as the player
// hits the ground and quickly jumps again.
LastCalcVeloMovementMode = MOVE_None;
const auto CurrentMovementMode = MovementMode;
if (LastCalcVeloMovementMode == MOVE_Falling)
{
    // NOTE Not using SetMovementMode() so that other code doesn't get notified.
    MovementMode = LastCalcVeloMovementMode;
}

// Ensure that friction isn't negative.
Friction = FMath::Max(0.f, Friction);
const auto MaxAccel = GetMaxAcceleration();
auto MaxSpeed = GetMaxSpeed();

#ifdef BG_ENABLE_STAMINA
// If stamina is enabled...
if (bEnableStamina)
{
    // Walking stamina logic.
    if (IsMovingOnGround() && Stamina > 0.0f)
    {
        // Mimic Counter-Strike's stamina logic for walking.
        const auto HorizSpeedMultiplierExponent = 70.0f * DeltaTime;
        const auto HorizSpeedMultiplier = FMath::Pow((MaxStamina - ((Stamina / 1000.0f) * StaminaRecoveryRate)) / MaxStamina, HorizSpeedMultiplierExponent);

        // Apply to the horizontal axis of our velocity only.
        Velocity.X *= HorizSpeedMultiplier;
        Velocity.Y *= HorizSpeedMultiplier;
    }
}
#endif // BG_ENABLE_STAMINA

// Apply fluid friction if necessary
if (bFluid)
{
    Velocity *= (1.f - FMath::Min(Friction * DeltaTime, 1.f));
}

// Get size and direction of acceleration.
const auto AccelDirection = GetSafeNormalPrecise(Acceleration);
const auto AccelAmount = Acceleration.Size();

// Apply ground friction first
if (ShouldApplyGroundFriction())
{
    ApplyFriction(DeltaTime, Friction, 1.0f, StopSpeed);
}

// Apply acceleration for movement.
if (IsMovingOnGround())
{
    ApplyAcceleration(DeltaTime, 1.0f, AccelDirection, MaxSpeed, AccelAmount);
}
else if (IsFalling())
{
    ApplyAirAcceleration(DeltaTime, 1.0f, AccelDirection, MaxSpeed, MaxFallAirSpeed, AccelAmount);
}

// Enforce the max speed limit (that can't be surpassed via bhopping or strafing) if enabled
if (bUseEnforcedMaxSpeed)
{
    Velocity = GetClampedToMaxSizePrecise(Velocity, EnforcedMaxSpeed);
}

// Restore the current movement mode again.
if (LastCalcVeloMovementMode == MOVE_Falling)
{
    // NOTE Not using SetMovementMode() so that other code doesn't get notified.
    MovementMode = CurrentMovementMode;
}
LastCalcVeloMovementMode = MovementMode;

I can imagine that this might be a bit hard to exactly translate into Blueprints, especially due to the frame-delayed movement mode switches described at the beginning and end of the snippet above.

Also you use a Variable named "Accelerate". And i dont really understand what this value is.

I don't see any variable simply called Accelerate in the code. The variable Acceleration is used though, and is provided by the UCharacterMovementComponent itself; the variable is updated each frame from the Pawn input vector consumed by UCharacterMovementComponent::TickComponent which is called from USD5BunnyGunCharacterMovement::TickComponent. Analog controls should be supported by extension.

One thing to maybe note though is that this code was last used with UE version 4.9 (31 Aug 2015), so I wont be too surprised if there are compatibility issues with the latest version of the engine. For this reason, I should probably archive this repository soon. One thing I can vouch for, however, is that the core logic behind the bunny-hopping, trimping and stamina systems should work.

I hope these answers provide at least some clarification and I wish you the best of luck with your endeavours! 😊

Kind regards, Sean.

Liquidmasl commented 5 years ago

Thank you very much for the thorough answer, i will read this probably 100 times and try to make this happen. I feel like i am kind of close, but just kind of..

I think the part where friction isnt appied for 1 frame can be implemented somehow differently, atleast for now (maybe with a simple timer).

Yes Acceleration was meant ofcourse! Until now i kinda skipped the TickComponent function. i will check this out. I could not find Acceleration in the UCharacterMovementComponent from blueprints, but maybe it hides somewhere else, or it was patched out sometime. But to my understanding this should just be wasd input direction (right, forward or 45 deg in any direction (wish direction)) and a magnitude that should be 1 (as it should be a unit vector when using normal keyboard and nothing analog)? Or it is the acceleration which is set as a default in the MovementComponent... i will try to find out! (if its something large it would makes sense that i move slower then a slug when i am missing this) But i will browse the documentation for this..

It seems i also have to look into CS stamina system, because i didnt even know that existed!

If you plan to retire this git i should clone it before its gone then :p Thanks again, 100 times, I hope i can make this happen now!

Greetings, Marcel

Liquidmasl commented 5 years ago

Hey Sean, i have one little question left for me, I hope I dont annoy tooo much!

I actually think my blueprints mimic your code quite okay. I just cant find anything that might be wrong. But i notices something, in your code you say MaxAcceleration = 6.0f; which seams to be (on your video) in m/s^2, (as you accelerate to 6m/s in a second easily.) the speed is shown in 600 uu/s when it hits 6m/s. (which seams to be max ground movement speed without bhoping)

I chose the same numbers as you did, as far as i can tell, but for me everything seems to be in uu and not m. My max movement speed (without friction) caps at 6uu/s. Which is just a pinch more then nothing.

In tzhe settings i made sure m is selected as unit everywhere, but that changed nothing really.

Is there something i am missing? some conversation i dont see or something?

Hope you can remember and help me out, thanks again, Greetings Marcel!

Edit: I tried scaling everything up 100, and playing around with friction and stop speed, but it doesnt really work. 600 feels like a good speed tho, friction just stops me down to around 7 though and jumping propells me instantly to 2000. I dont understand why air acceleration is so high in cs, i mean it doesnt feel like i am accelerating any faster while jumping then walking. Something about this value i dont get really.

Liquidmasl commented 5 years ago

alright, nevermind, i think i got it, huuurrrraaayy

I misread the code and i feel so dumb right now.

Acceleration magnitude is 6, and wishspeed is 700. Me, an idiot, thought wishspeed would be 6, and accel amount something i did not understund. After another 100 reads i finally got it!

That the function param is called wish speed, and max speed is handed over, kinda got me.

Everything seems to work fine now, character seems a bit floaty but i think thats just me beeing picky. Thank you again for this code.

I am so relieved !

Have a wonderful day!