How to move character with permanent speed in Unity2D - unity3d

I'm creating Unity2D runner where characters is running on the ground.
I'm trying to force him run with constant speed by applying force with right vector but the movement is jerky.
I'm trying to achieve effect of endless run with permanent speed. It is easy in the air but works different (because of physics) when character is running on the ground.

You could velocity and make sure to turn off gravity. If you are running on the ground make sure you turn this off.
You could implement your own movement where you can update position depending on Time.deltaTime.
Just use the built in character controller that unity comes with. basic directionals and jump. And mouse controls where the character faces.
EDIT:
Use rigidbody velocity and turn off gravity and drag. This will keep your runner running forever.
To implement this yourself. You can update the position of the object in the update method. Something like
Vector3 temp = object.transform.position;
temp.x = speed * Time.deltaTime;
object.transform.position = temp;
Where object is you runner and speed is how fast you would like him to move.
This would be inside the update function.
If you aren't going to be controlling the runner, dont bother with the controller

Use Rigidbody2D.velocity and pay attention to:
The velocity can also gradually decay due to the effect of drag if
this is enabled.

Related

How do I check for and resolve collisions within FixedUpdate using a kinematic rigidbody?

I have been working on my own kinematic character controller for a while, but only recently learned that one should consider updating its position and rotation using Rigidbody.MovePosition and Rigidbody.MoveRotation instead of directly modifying the Transform component, which is what I am doing now. While my controller works fine, and does not cause any noticeable performance impact in my small games, I want to better understand the benefits of manipulating the Rigidbody component, and especially how this all works within FixedUpdate instead of Update.
To be clear about the supposed impacts on performance, Unity's manual on 2D rigidbodies says:
Any Collider 2D component added to the same GameObject or child GameObject is implicitly attached to that Rigidbody 2D. When a Collider 2D is attached to the Rigidbody 2D, it moves with it. A Collider 2D should never be moved directly using the Transform or any collider offset; the Rigidbody 2D should be moved instead. This offers the best performance and ensures correct collision detection.
Right now, my basic controller loop looks like this in the Update method:
Read the user's input velocity
Modify the controller's velocity based on this input (this velocity is distinct from Rigidbody.velocity)
Using Physics queries, sweep the controller's body against the appropriate collision layers by velocity * Time.deltaTime
Pick a collision resolution position based on a set of rules
Set the controller's Transform.position to this resolution position
I also have a method that moves the controller using Transform.Translate if no collision detection is needed.
As you can see, though my controller GameObject has a kinematic rigidbody attached to it, I never actually use it for anything. Unity's documentation on kinematic rigidbodies is conflicting, stating here:
Note: MovePosition is intended for use with kinematic rigidbodies.
but also here:
If isKinematic is enabled...The rigidbody will be under full control of animation or script control by changing transform.position
I am also unsure about how to manually check for collisions within FixedUpdate, as I have read that FixedUpdate can be called more than once per frame. Frankly, I thought FixedUpdate was only supposed to be used with dynamic rigidbodies to simulate real physics, and thus have only used this method for simple manipulation of those kinds of rigidbodies.
And then Rigidbody.MovePosition states that
2D rigidbodies have a fixed limit on how fast they can move therefore attempting to move large distances over short time-scales can result in the rigidbody not reaching the specified position during the next physics update. It is recommended that you use this for relatively small distance movements only.
What if my character needs to move a very large amount? Do I just set Rigidbody.position directly?
I guess I am trying to figure out how I can reconcile all of this logic to conform to what Unity says is best for performance. Perhaps I need to combine Update and FixedUpdate, but ultimately I am just hoping to receive some clarification and guidance regarding all of this.

Unity Player passsing through objects

player and object both have colliders and rigidbodies, object has position and rotation locked, player has only rotation locked. When the player goes to the blocks, the player goes through the blocks, although they do give a bit of resistance. To move the player im setting the rigidbody's velocity, and doing that in FixedUpdate.
i have no idea why this is happening, any ideas?
main part of the code is:
rigidBody.velocity = new Vector3(direction.x, rigidBody.velocity.y + (-Gravity * Time.deltaTime), direction.z);
(direction is determined by the WASD keys, and i'm using my own gravity)
First of all, you do not need to multiply the velocity by time.DeltaTime, because you are moving your object in the FixedUpdate() method; Which uses fixed time intervals since the physics engine does not run in sync with the regular game engine. Also, both objects do not need rigidbodies in order to collide with one another. I suggest looking at your collision matrix in settings and verifying that everything you need collision for is checked correctly. As others have said as well, check your kinematics on the rigidbody.
A last suggestion for working with your own gravity. Do not change the actual gravity value of the game engine. It is typically recommended that you use a multiplier variable and apply it to the constant gravity already set by the physics engine. If you are completely editing the gravity, than maybe consider using a character controller instead.
I guess it has something to do with what the documentation says "In most cases you should not modify the velocity directly, as this can result in unrealistic behaviour".
Try to use AddForce() or similar functions to alter the properties of the rigid body. Colliders etc will then work as expected.

Best way to move a game object in Unity 3D

I'm going through a few different Unity tutorials and the way a game object is moved around in each is a little different.
What are the pros/cons to each of these methods and which is preferred for a first person RPG?
// Here I use MovePosition function on the rigid body of this component
Rigidbody.MovePosition(m_Rigidbody.position + movement);
//Here I apply force to the rigid body and am able to choose force mode
Rigidbody.AddForce(15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
// Here I directly change a transforms position value, in this case the cam
Transform.transform.position = playerTransform.position + cameraOffset;
Thanks!!
EDIT;
Something I have noticed is that the applied force seems to memic wheeled vehicles while the position changes memic walking/running.
RigidBodies and Velocities/Physics
The only time, I personally have used the rigidbodys system was when implementing my own boids (flocking behaviour) as you need to calculate a few separate vectors and apply them all to the unit.
Rigidbody.MovePosition(m_Rigidbody.position + movement);
This calculates a movement vector towards a target for you using the physics system, so the object's velocity and movement can still be affected by drag, angular drag and so on.
This particular function is a wrapper around Rigidbody.AddForce I believe.
Pros :
Good if realistic physical reactions is something you are going for
Cons:
A bit unwieldy to use if all you are trying to achieve is moving a object from point A to point B.
Sometimes an errant setting set too high somewhere (for example: Mass > 10000000) can cause really screwy bugs in behaviour that can be quite a pain to pin down and mitigate.
Notes: Rigidbodies when colliding with another Rigidbody would bounce from each other depending on physics settings.
They are also affected by gravity. Basically they try to mimic real life objects but it can be sometimes difficult to tame the objects and make them do exactly what you want.
And Rigidbody.AddForce is basically the same as above except you calculate the vector yourself.
So for example to get a vector towards a target you would do
Vector3 target = target.position - myPosition;
Rigidbody.AddForce(target * 15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
If you don't plan on having any major physics mechanics in your game, I would suggest moving by interpolating the objects position.
As it is far easier to get things to behave how you want, unless of course you are going for physical realism!
Interpolating the units position
Pros :
Perhaps a little strange to understand at first but far simpler to make objects move how you want
Cons:
If you wanted realistic reactions to objects impacting you'd have to do a lot of the work yourself. But sometimes this is preferable to using a physics system then trying, as I've said earlier to tame it.
You would use the technique in say a Pokemon game, you don't stop in Pokemon and wait for ash to stop skidding or hit a wall and bounce uncontrollably backwards.
This particular function is setting the objects position like teleporting but you can also use this to move the character smoothly to a position. I suggest looking up 'tweens' for smoothly interpolating between variables.
//change the characters x by + 1 every tick,
Transform.transform.position.x += 1f;
Rigidbody.MovePosition(m_Rigidbody.position + movement);
From the docs:
If Rigidbody interpolation is enabled on the Rigidbody, calling Rigidbody.MovePosition results in a smooth transition between the two positions in any intermediate frames rendered. This should be used if you want to continuously move a rigidbody in each FixedUpdate.
https://docs.unity3d.com/ScriptReference/Rigidbody.MovePosition.html
Rigidbody.AddForce(15 * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
This will make the object accelerate, so it won't travel at a constant velocity (this is because of Newton's second law, Force=mass*acceleration). Also if you have another force going in the opposite direction this force could get cancelled out and the object won't move at all.
Transform.transform.position = playerTransform.position + cameraOffset;
This will teleport the object. No smooth transition, no interaction with any forces already in the game, just an instant change in position.

Make Physics more accurate

I make a 2D-game. In this game, I have a projectile, which I move the fires by myself like this:
void Update()
{
gameObject.transform.position = new Vector3(
gameObject.transform.position.x + baseVelocity * Time.deltaTime,
gameObject.transform.position.y + baseVelocity * Time.deltaTime,
gameObject.transform.position.z);
}
And also, I use void OnTriggerEnter2D(Collider2D other) to know when collisions occurs.
The problem is when game running on a weak phone with 30-FPS it won't detect collision, while same fire in an 60-FPS phone will collide.
I think this is because the fires move 2x more in 30-FPS phones.
One option was use FixedUpdate() method for moving fiers, but it gave me jerky movement, and I used Update() method for moving because it gives me smooth movement(in both of them I used Time.deltaTime).
Can you please suggest me how make more accurate while using smooth movement?
like move object in Update() method but check object position in more(offset) positions than where it is!
I forget to note that I changed the value of Fixed TimeStep to 0.01 for getting more accurate physics.
Thanks in advance.
edit:
I finally end up with using FixedUpdate() for move objects by myself, for so many reasons I can't use Physics engine, I set FixedUpdate TPS(tick per second) around 60 to some how be match with my 60 FPS Update (and still can't figure out why increase FixedUpdate TPS will make object movement jerky!).
And will keep this question open for finding better answer.
You seem to be doing the physics manually. The issue with manually updating the position is that you don't know about the position of your projectile between frames. Even if you were to use FixedUpdate, you could still be in the situation where two FixedUpdate calls cause your projectile to miss an object.
So instead of manually updating the position, you should use a RigidBody2D, with the collision detection set to "Continuous". A continuous collision detection will interpolate object collision in between physics update cycles, so you hit your target even at very high speeds. Also, this solution does not depend on frame rate.
Note that the above will only work if you don't manually update your positions yourself. That is because the physics engine uses velocity to calculate collision in between physics update cycles.
So instead of updating the position yourself (which is bad for physics), use forces instead.
Or alternatively, if you don't want to mess with forces, update the velocity instead:
GetComponent<RigidBody2D>().velocity = baseVelocity;

How to use AddForce and Velocity together?

I have the jump component who use the AddForce for jumping and the movement component who move left and right using the Velocity.
If you don't move the character when your are jumping the jumping will be fine but when you move the character and jump at the same time then the movement component will break the jumping because the velocity is setting up a Vector2 point where define the Y axis too. I tried to use the current Y axis from the transform component in the movement but even that doesn't work.
What I should do for fix the problem between AddForce and then use Velocity?
It seems your move function is creating a new velocity vector and overwriting the existing one.
Vector2 velocityVector = rigidbody.velocity;
velocityVector.x += movement * force;
rigidbody.velocity = velocityVector;
This will retain the existing velocity, both X and Y, and modify it. You will of course need to add deceleration (usually I use something along the lines of if(grounded) velocityVector.x *= 0.999f;, but I'm sure more fancy maths exists for more realistic deceleration) and some kind of maximum speed (again, I keep things simple and use similar to if(velocityVector.x > maxSpeed) velocityVector.x = maxSpeed;).
Rigidbody.AddForce has the following definition:
public void AddForce(Vector3 force, ForceMode mode = ForceMode.Force);
One of the options available for ForceMode is ForceMode.VelocityChange:
Add an instant velocity change to the rigidbody, ignoring its mass.
Apply the velocity change instantly with a single function call. In contrast to ForceMode.Impulse, VelocityChange will change the velocity of every rigidbody the same way regardless of differences in mass. This mode is useful for something like a fleet of differently-sized space ships that you want to control without accounting for differences in mass. In this mode, the unit of the force parameter is applied to the rigidbody as distance/time.