Why does Character Movement override Add Force?

Hello,
I am working on a game which has a water current element to it. I want the flow of the water to move the character realistically (i.e. push them in one direction, if they swim in the opposite direction, then the flow should make them move slower etc.).

The max swim speed for the character is set to 1,000.0. So if the flow speed of the water is 500.0, I would like the character to swim at 1500 downstream and 500 upstream. But this does not seem to be working.

I have tried several different ways to accomplish this, but the closest that I have come so far is by using the AddForce() method from the UCharacterMovementComponent (I found that adding a float value of 5,000.0 gives me the best effect) . This seems to work fine, if the character is simply riding the flow - he will keep accelerating all the way up to about 1,900.0. However, if I move the character, then the Movement component seems to override the force and he suddenly brakes down to 1,000.0. Also, the character is able to swim upstream at 1,000.0.

Am I doing something wrong by using AddForce to this end? Or would it be best to create a new movement class and override some of the methods?

Any suggestions would be appreciated.

Thanks in advance

OK, so here is an update on the situation…

I found out that I was adjusting some variables incorrectly when I was getting the clamped speed issue. I just needed to increase the amount of force being added to the character to increase the speed threshold. This also seemed to get rid of the max swim speed overriding the force in the downstream direction.

But I still have one issue left. The character is still able to reach their max swim speed when swimming upstream.

As I had described above, I want the force to effect the player so that they will swim MaxSpeed + DownstreamCurrentSpeed when swimming downstream, and only be able to swim MaxSpeed - DownstreamCurrentSpeed when swimming upstream.

I think that I understand WHY this is happening (I am adding force to the character, but I am not directly affecting the character’s Velocity. So, the CharacterMovementComponent is still allowing enough forward movement to reach the MaxSwimSpeed).

What I don’t know is how to fix it. I am beginning to think that using AddForce() is not the best way to get the desired effect that I am looking for. But I have already tried using AddInputVector() as well as trying to manipulate the Velocity directly. And neither if these worked very well. (I also tried AddImpulse()… with some rather hilarious results).

If anyone has any suggestions on how to fix this upstream swimming issue, or if you have a better way to get the desired effect, I would be most appreciative.

Thanks

#PhysX Kinematic vs Simulating

“Am I doing something wrong by using AddForce to this end?”

Characters are Kinematic , regular physics objects are “simulating

Simulating actors respond to add force and add impulse

Kinematic actors ignore both :slight_smile:

Use CharacterMovement->Velocity += your impulse to push characters the way you want to

#My C++ Code For You
YourCharacter->GetCharacterMovement()->Velocity += Force;

#:heart:

Rama

Thank you for the help. I had been wondering if I was barking up the wrong tree with the AddForce thing, But when I discovered that it worked on non-physics enabled Characters (through the CharacterMovementComponent) I thought that maybe it would work.

My problem is that the feature that I am adding will allow the player to remain in it (and thereby affected by it) indefinitely. So I am updating every tick. Now maybe I am over-thinking this, but if I add the Velocity every tick, that will accumulate and get vary high very fast. (I have tried this and was almost instantly launched into hyperspace). So I would have to meter the Velocity in order to prevent it from getting out of control.

I could do this by Capping the Max Total Velocity Magnitude at MaxSwimSpeed + CurrentFlowSpeed. But that would Only cap it in one direction (I tried this one too and immediately lost almost all control of the character in the Current). I am looking for a way to allow the player to swim against the current, even if doing so only slows forward movement a little.

So, the only other solution that I can think of is to add it to the PendingInputVector just before the total movement is calculated. Which means that I would have to override the Movement Component - fair enough. But, since the CharacterMovementComponent member will soon become Private, I can’t replace it in a child class (can I?). And I don’t want to run the risk of one movement class mucking up the calculations of another one within the same character class. So does that mean that I have to make my player class a sibling class in order to get the effect that I am looking for? Surely that is not the case.

As I already said, I am probably over-thinking this. So, please just tell me how much of a dimwit I am and that I just need to do Foo to the Bar. Because otherwise I will probably tear out all of my hair trying to figure this out!

Thanks

p.s. If you need me to post code, I can… But I keep changing it about every ten minutes or so to try a different approach.

Change in velocity IS force. So if you want the current to be applying a constant force, then you should be applying a constant change in velocity (i.e. constant additions to velocity every tick). Select a force value and multiply it by the DeltaTime value to bring it down to manageable levels. That should also mean that whatever value you select will be equal to force per second (Unreal Newtons per second?).

As for the max-speed thing, I would look inside the character movement component’s CalcVelocity function and try to figure out what exactly caps out the max speed. Maybe the CharacterMovementComponent deliberately scales up the input forces on the character in order to meet the max velocity quota. I would look for you myself but I am about to sleep.

That’s just my two cents, as someone who is also trying to do some physics-based character movement. Maybe Rama will have something that can help you more precisely. Either way, good luck!


EDIT: I forgot mass in my earlier mention about force being change in velocity. As I said, sleep soon. Anyway, what I was describing was this:

change to velocity each tick = ForcePerSec * DeltaTime / CharacterMass

Since the second two variables are ‘given’, this means the float you provide is a legitimate force per second value. I don’t know if you did any research into how powerful water currents are but if you did, you could put your newton per second value in there and it would behave fairly realistically.


EDIT 2: I have since implemented my own force/impulse function and found that the ForcePerSec value needs to be 100 times greater than what you would expect for real-world numbers. I think this is because the standard units for space are Unreal Units, which are, effectively, centimetres. Newtons are normally kgm/s^2, but in this case we use kgcm/s^2, meaning all force values will need to be 100x normal.

Rama is correct once again.

However, I would like to make some clarification on this one for posterity sake.

First of all, AddForce() DOES work for kinematic Actors such as the ACharacter class (as does AddImpulse()), as long as it is done through the CharacterMovementComponent. However, this is most often going to be something that is not necessary because, as Persnickety pointed out, force is really just a change in Velocity. The only real reason to bother using AddForce on a Character would be if you wanted the velocity to be scaled by their mass (which is what force is). So, for all my research on force calculations, I finally came to the conclusion that all I really wanted to do was add velocity to the character.

The problem with simply adding velocity every tick is that it is difficult to put a cap on the value. The engine will eventually cap the velocity based upon friction calculations, etc. But, in order to have complete control over the velocity, I decided that it would be easier to create a separate class that would handle just that.

Eventually, I created a UActorComponent class, called UVelocityManager, which handles the velocity of the character. It might seem redundant, since the movement component already does some of this. But, because of the difficulty with getting precise control over the added velocity, this seemed to be the easiest solution.

If I get time, I will post a tutorial on just how to make such a class, and what it does exactly. But, in a very brief description, it basically alters the max movement speed based upon the speed of the current and which direction the character is moving within that current.

So, Thank you very much to both Rama and PersnicketyGareth for their Swift and helpful replies.

How can I use the AddForce or AddImpulse through the CharacterMovementComponent? I use it but it wont move my character.