AddForce instead of modyfing Velocity

I just realized that if i want to use physics with rigidbodies2d i cant move the player or character by modyfing Rigidbody2D.velocity.
So how do i do it?

Im getting the movement input from GetAxis(“Horizontal”) and i want the character to move left or right depending on this. Its easy if i want to use velocity but how would i convert this to AddForce?

‘velocity’ and AddForce() are very different. Imagine a space ship heading in some direction and you add some force from the side (perpendicular to the direction the ship is traveling). The ship does not make an immediate 90 degree turn. Instead the force turns the ship towards the new direction some. The more the force, the more the angle of the new direction is different from the old. The current move vector and the force are added together to get the new direction.

With velocity, you get an immediate change in direction. So if your ship was headed directly up in your 2D game and you did:

rigidbody2D.velocity = Vector3.right;

Your ship would make an immediate turn towards the right. Note you can split the difference somewhat. Rigidbody2D.drag makes AddForce() act more line an immediate velocity assignment. The higher the drag, the faster an object sheds old velocity and takes on new velocity. Of course you have to add more force and continue to add force each frame to overcome drag. As for “Horizontal” and velocity, In FixedUpdate() you can put:

rigidbody2D.velocity = Vector2(GetAxis("Horizontal") * maxSpeed, 0.0);

I ran into similar problems as you OP and I tried the Accepted answer. While it worked, manually clamping the velocity is problematic and can make for a confusing applied physics system (it seems bad to mix force and velocity management in practice). An approach that allowed me to maintain one system of speed management was to scale the force applied in terms of the current velocity as a percentage of max velocity.

float xcap = (rigidbody.velocity.x / maxWalkingSpeed)*moveHorizontal;
		if (xcap > 0) {
			maxVelocityScalerX = Mathf.Clamp( 1.0f - xcap, 0.0f,1.0f);
			movement.x *= maxVelocityScalerX;
				}

		float zcap = (rigidbody.velocity.z / maxWalkingSpeed)*moveVertical;
		if (zcap > 0) {
			maxVelocityScalerZ = Mathf.Clamp( 1.0f - zcap, 0.0f,1.0f);
			movement.z *= maxVelocityScalerZ;
		}

		

		rigidbody.AddForce(movement*speed*Time.deltaTime, ForceMode.VelocityChange);

This also has an added benefit of allowing your game actors to pass your manually set velocity cap due to outside forces. This helps maintain a more realistic feel to your movement.

I got the same problem and fixed it, NARROWLY since some remains to be test more.
As for that you can’t use the velocity or the force added to it will be in vain. So my solution is to set a limitation speed for CONTROL, meaning that you can only control the character within some speed using “addForce” function and since I can only control the horizontal direction, the limitation should just be for “x Axis”, instead of the magnititude of the velocity. Here is the code.

			if(Input.GetButton(m_HorizontalInput))
			{
				if(Mathf.Abs( GetComponent<Rigidbody2D>().velocity.x )<= MoveSpeed)
					GetComponent<Rigidbody2D>().AddForce (Vector2.right*Input.GetAxis(m_HorizontalInput)*Accelerate, ForceMode2D.Impulse);
				else
				{
					GetComponent<Rigidbody2D>().velocity = Vector2.Lerp(GetComponent<Rigidbody2D>().velocity,Vector2.up * GetComponent<Rigidbody2D>().velocity.y,Time.deltaTime * 5.0f);
				}
			}
			else
			{
				GetComponent<Rigidbody2D>().velocity = Vector2.Lerp(GetComponent<Rigidbody2D>().velocity,Vector2.up * GetComponent<Rigidbody2D>().velocity.y,Time.deltaTime * 5.0f);
			}

This is similar to how Mario handles physics-based movement:

rigidbody2D.velocity = new Vector2(CrossPlatformInputManager.GetAxis("Horizontal"); * yourMoveSpeed* Time.deltaTime, rigidbody2D.velocity.y);

what this does is slowly accelerate up to your movement speed, then decelerate when you stop moving left or right. You can see that the deltaTime is accessed to make sure this is handled precisely. Don’t try to use a ‘+=’ with velocity, either, it will make you move insanely fast, as it will keep increasing your velocity forever. (remember += means that the new value is being added to the old, then set as the new value)

Unity would really benefit from creating a series of tutorials where they teach you how to emulate controls in other games, rather than giving you the most basic way to accomplish something. I’d appreciate it, anyway.