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.
Related
I'm trying to make a pick up objects mechanic like the one in Amnesia. It's easy to calculate needed rigidbody's velocity, so that the held object stays in front of camera, but my problem is that the object doesn't rotate at all when I hold it. And I would rather have it always be rotated towards the camera. This could easily be achieved with simply parenting the object to player's camera, but...
The behaviour I'm after is as follows: if the bottle I picked up was standing on a table, with neck of the bottle facing ceiling, I would like to see this bottle always with its neck facing ceiling while I hold it. But if this bottle collides with something, it should behave like it actually bumped onto something, so it should rotate some small amount, but it should always try to return to its "original" rotation (in this case, neck facing ceiling).
I think that I need to calculate angular velocity for that and probably have some lerp to return to original rotation, but I'm at a loss on how to do that properly.
I think that the first thing I would need to do is to store the initial direction the moment player picks object up:
Vector3 targetDirection = playerCamera.transform.position - transform.position;
Script is on the held object, so "transform" refers to it. In FixedUpdate() I probably need to have some interpolation, so that angular velocity always tries to rotate the object to original rotation:
rigidbody.angularVelocity = Vector3.Lerp(rigidbody.angularVelocity, targetAngularVelocity, lerpSpeed * Time.fixedDeltaTime);
I don't know how to calculate targetAngularVelocity, because after all I would like the held object to return to original rotation smoothly. I'm not even sure if that's the right way to do this thing and perhaps I should do something else than to calculate angular velocity needed to rotate object properly. I tried just interpolating localRotation to original local rotation, but that did not allow the held object to bump on stuff (the movement then was very jittery). Any ideas?
You need a stabilizer. A script which will add torque/angular velocity to the object, whose angle is different from the target one. Say, you have two variables: targetDirection and currentDirection aka transform.forward. Then you write something like this in fixed update:
var rotation = Quaternion.FromToRotation(currentDirection, targetDirection).eulerAngles * sensitivity;
rigidbody.angularVelocity = rotation;
I recommend to set sensitivity about 0.05 and then increase it if the object stabilizes too slow.
Probably I confused the order, so you should put minus somewhere, but the approach itself is applicable.
What is the ideal way to implement projectile physics, like a cannonball or arrow? I've been experimenting with BodyForce / BodyVelocity but those look like they're applying a constant, non-diminishing force / velocity to the projectile which doesn't look realistic. I've also just set the Velocity property of the projectile directly which works better, but I'm assuming there's a standard pattern used for something like this.
In physics, velocity is split into 2 components, the vertical component and the horizontal component. When a projectile is in motion through the air, we don't consider air resistence affecting its speed, as it's such a minute force.
Since velocity is split into 2 components, if velocity changes or is applied horizontally, that horizonal velocity or force does not affect the vertical force or velocity, and vice versa. This is why projectiles travel at a constant speed horizontally. The vertical velocity, however, is not constant. Due to gravity, the projectile will fall to the earth faster over time. This is acceleration.
What you could try is to add a body velocity with a high value, such as 400,400,0: a velocity for the x, y and z axis, and then immediately remove the velocity a fraction of a second later. What this does is creates an initial velocity, which eventually gets changed by gravity on the y component.
To learn more about projectile physics, you can check out online resources such as the following:
http://bowlesphysics.com/images/AP_Physics_B_-_Projectile_Motion.pdf
What i'm looking to do is something similar to our solar system, where you are gravitically drawn to one planet till you leave it's pull, and then once you're on another planet be drawn to that gravity.
I have found many entries online about how to create gravity for a single planet, but none i've found work for multiple sources.
Any help would be GREATLY appreciated.
Projects I've already looked at were mainly for single planet gravity.
unity 3.3, create local gravity on object
http://answers.unity3d.com/questions/13639/how-do-i-make-a-small-planet-with-gravitational-pu.html
http://answers.unity3d.com/questions/701618/how-could-i-simulate-planetary-gravity-that-has-an.html
This could be done easily by adding a normal force relative to the planet on the surrounding objects.
According to physics of Universal gravitational force you can calculate the gravitational force. Then calculated the normal force at the moment and add the force.
void FixedUpdate(){
// Do the Force calculation (refer universal gravitation for more info)
// Use numbers to adjust force, distance will be changing over time!
forceSun = G x (massPlanet x massSun)/d^2;
// Find the Normal direction
Vector3 normalDirectionSun = (planet.position - sun.position).normalized;
// calculate the force on the object from the planet
Vector3 normalForceSun = normalDirection * forceSun;
// Calculate for the other systems on your solar system similarly
// Apply all these forces on current planet's rigidbody
// Apply the force on the rigid body of the surrounding object/s
rigidbody.AddForce(normalForceSun);
// .... add forces of other objects.
}
With various m1, m2 values you will be able to make the system more realistic. As an example make the object move/accelerate towards the planets with higher mass.
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.
I have an object which is affected by gravity and collision effects.
How can I make it to maintain a constant velocity on the X axis?
I have something like that:
void Update () {
rigidbody.velocity = 5 * new Vector3(1f,0f,0f);
}
Note that the physics engine is updated at a different interval than other basic game logic.
In particular, the state of the Rigidbody is updated once per call to FixedUpdate(), thus if you want to override any results of the physics engine you probably want to do it inside your own FixedUpdate(), instead of Update().
If you really want the object to have constant speed no matter what, then you don't want it to be affected by collisions and gravity. In this case, you should check Kinematic checkbox in rigidbody's properties. This way, you'll be able to move the object's transform from the script, and the object's location won't be affected by anything else.
Aside from what everybody has already told you I would add that if you want to keep a constant speed on a particular direction (X axis in your case) a more correct code would be :
void FixedUpdate () {
// We need to keep the old y and z component if we want the object to still be affected by gravity and other things
rigidbody.velocity = new Vector3(5.0f , rigidbody.velocity.y, rigidbody.velocity.z);
}