#Applying external forces to object without Unity physics

1 messages · Page 1 of 1 (latest)

vagrant warren
#

Hi all,

I'll get right to the point:

My game, a 2D platformer of sorts, uses Unity's tilemap system for terrain, but characters (and as much else as I can manage) will be controlled with my own movement system using raycasts and direct transform adjustments, as I did in my first project (years ago, at this point).

The bug I'm fighting with seems to be less specific to the scenario in which I was seeing it than I initially thought, and is likely to be indicative of a broader flaw in my design. In this case, though, I'm trying to make my character do a little hop (like knockback) straight up into the air when they touch something hot. This can be regular game objects (projectiles, enemies, burning decorations) or tiles that have a burning flag set.

My movement code checks to see if a touched tile has any effects that it should apply to it (the moving object, such as the player), and sends that message before returning true (if ground/ceiling/wall is hit) and false if not. The return value is used in the PlayerController to set states such as grounded, stop accumulation of upwards velocity (if jumping and hitting a ceiling), and (eventually) pushing against a wall/obstacle.

You might already see the potential issue here: The movement code detects a (in this case) burning tile, which calls OnTouchedBurningTile() on the player, starting the hop, but the last part of that code tells the PlayerController that a floor has been detected, so the player should be grounded and the vertical velocity should be zero'd out. This results in a very tiny hop that's only perceptible if I set the value super high to compensate, which is what I've been doing just to ensure that something is happening.

I could set up a bunch of flags to allow for this exception, but I think a cleaner solution is needed. Any help at all would be greatly appreciated.

Here is the relevant code: https://paste.mod.gg/fsqhunxlyzyj/0

Thanks to anybody that gives this their time.

dusk tusk
#

I'm not going to be able to read this code, but to give a general thought ... typically when you are making kinematic character controllers (ie, you are doing your own physics), you very rarely override the velocity of the CC unless in very specific cases such as teleporting or respawning.

Instead, you apply the force to the existing velocity of the player. In the case of the knock back, you would that that backward + upward force, or if you want it to be immediate, then you could apply it directly as the new velocity of the player.

What you do control though, is the state of the CC and whether or not things such as player input is allowed. For example, your CC might now be in the PlayerState.Knockback state for a set duration and you might ignore input so that the entire thing has to play out. Or if you don't, then any input would not override the velocity, but instead be applied to it per frame to allow the player to "push back" against it.

vagrant warren
# dusk tusk I'm not going to be able to read this code, but to give a general thought ... ty...

That is actually quite insightful. My previous project that used kinematic CC (thanks for the terminology) was simple enough that it never came up beyond brief experiments that I must have tossed out before understanding the problem.

In my case, the knockback is setting the velocity of the player, but this doesn't actually do anything to move them until it is passed to the MovementController, but those calls (one for horizontal, one for vertical) already happened that frame, and are (if I'm understanding correctly) overwritten before they can be used. One of my unsuccessful solutions involved simply calling the MovePlayer function within the Knockback function, but this didn't have the intended effect. Maybe I can just call the MovementController functions in there instead.

I have considered using a state that blocks (at least some) player input for things like knockback, but I think what I'm currently fighting is gravity, which I pobably shouldn't block in this case.

Thank you for the response, by the way.

dusk tusk
#

Yeah, you don't want to do multiple moves per frame. You want to calculate the final velocity of the frame before moving the character. This would be an accumulation of the player's input, gravity and other forces acting on the player such as a knockback.

This allows you to essentially stack influences such as an extreme case where the player is knocked back while trying to move against it while there's a wind blowing the CC to the right while they're sliding on ice at the same time, etc. etc.