accelerated addforce for rigidbody - unity3d

I need a method for accelerating the addforce method to the object.
Force Result feels too slow and I want it to be applied faster and for the final result time lapse shorten.
void FixedUpdate()
{....
Vector3 v_x = new Vector3(keyb_x, 0, 0);
Vector3 force_ = v_x * kspeed * Time.deltaTime;
float speed = rigidbody.velocity.magnitude;
rigidbody.AddForce(force_, ForceMode.Impulse);
....}
Raising gravity from -9 to -19 or more in the y direction gives the expected result, but all other objects are affected. I want only it to apply to a specific object only.

All gravity does is apply a downward force to all of your rigidbodies every physics update. For 2D unity physics you could use rigidbody2D.GravityScale, which scales gravity's effect on a per-rigidbody basis, but for 3D rigid bodies you should apply a constant force equal to the change in gravity you want for your object
e.g.
//adds a downforce of 10 per second
rigidbody.AddForce(Vector3.down * 10f * Time.fixedDeltaTime);
You'll want to put this in your fixed update function.

object_Rigid2D.gravityScale += gravity_Increase * Time.deltaTime;

I found an easy way to reach this. Consider you have an object which you move with addForce (I use impulse, other modes probably work too) by 1 unit (so vector is something like (1, 0, 0)) and object mass and drag are both 1, so the object moves properly but you want to make it quicker/slower. In that case you need to reduce it's mass and increase drag to make it quick and vice versa. For example you can make it quicker if you set mass to 2 and drag for 0.5 or slower if mass is 0.25 and drag is 4. Only rule is that drag * mass = 1.

Related

Unity rope swinging physics algorithm: Player stuck mid-swing

I have implemented the following tutorial in Unity (2D) attempting to create a rope swinging platformer: https://gamedevelopment.tutsplus.com/tutorials/swinging-physics-for-player-movement-as-seen-in-spider-man-2-and-energy-hook--gamedev-8782
void FixedUpdate()
{
Vector2 testPosition = playerRigidbody.position + playerRigidbody.velocity * Time.deltaTime;
Hooked(testPosition);
}
private void Hooked(Vector2 testPosition)
{
Vector2 t = new Vector2(tetherPoint.position.x, tetherPoint.position.y);
Debug.DrawLine(tetherPoint.position, playerRigidbody.position);
float currentLength = (testPosition - t).magnitude;
if (currentLength < tetherLength)
{
currentLength = (playerRigidbody.position - t).magnitude * Time.deltaTime;
}
else
currentLength = tetherLength;
if ((testPosition - t).magnitude > tetherLength)
{
Vector2 x = (testPosition - t).normalized;
testPosition = new Vector2(x.x * currentLength, x.y * currentLength);
playerRigidbody.velocity = (testPosition - playerRigidbody.position) * Time.deltaTime;
playerRigidbody.position = testPosition;
}
}
It seems to function correctly on the downward swing but when the player begins to travel upwards they become stuck floating in the air and don't drop to the middle of the arc. The swing also does not propel them very high on the other side even when dropped from height.
EDIT (Further clarification): Interestingly When the player is dropped from the other side of the tetherPoint it stops in the same spot, this time only half-way down. It's as if the player is being pulled toward a single position even when manually moved in the editor while playing no matter the direction.
EDIT: User John cleared up my concerns about deltaTime.
I've tried examining the change in variables during play but I just can't figure out why it's not working correctly. I think the issue lies somewhere in my interpretation of the original psudeo-code to C#.
Another question on the same tutorial has been asked previously but unfortunately that users implementation was very different than mine: Game rope swing physics acting weird
EDIT: Since posting I've updated the code to use AddForce and MovePosition instead but it's still the same.
playerRigidbody.AddForce((testPosition - playerRigidbody.position) * Time.deltaTime);
playerRigidbody.MovePosition(testPosition);
It looks like you're using Time.deltaTime from a method that is called from FixedUpdate. What you want to use instead is Time.fixedDeltaTime.
FixedUpdate is called at a set interval (eg. 50fps) for physics updates, but regular Update is called at a different varying frequency (up to hundreds of times a second if you've got a fast computer/simple game).
Time.deltaTime is used for the Update method, and so the value of it can be different each time Update is called, as the time between Update calls varies.
However, because FixedUpdate is called at the same interval each time, Time.fixedDeltaTime is constant and (normally) much larger than Time.deltaTime. Your code doesn't work well with Time.deltaTime, as it doesn't represent the actual difference in time between each FixedUpdate call, but Time.fixedDeltaTime should work.
As a side note, you're correct that you should be multiplying by the time delta rather than dividing. the time delta should be multiplied when calculating positions (eg. for the Vector2 testPosition assignment and the currentLength calculation), but for calculating the velocity you should be dividing the time delta (because velocity = distance/time).

unity movement, object keeps falling even when key is held down

I'm still new to unity and I'm trying to create controls for a hot air balloon, however even though I'm still holding down the up arrow the object ends up falling after a few seconds and I'm not sure why.
if (Input.GetKey(KeyCode.UpArrow))
{
transform.position += new Vector3(0, 1, 0) * Time.deltaTime * speed;
fuel = fuel - 3 * Time.deltaTime;
}
When you say that the object is "falling" I take that to mean that you've added a Rigidbody (or Rigidbody2D) component to it with gravity enabled.
If you're using a Rigidbody to simulate gravity, you can't just manually manipulate the position like this. You'll want to use Rigidbody.AddForce() instead.

Why do objects get stuck together in Unity?

I have a 2D scene that consists of 4 sprites, each with a box collider.
I then have a prefab that is simply a sprite of a circle with a 2D circle collider.
Finally I have a script named Atmosphere attached to my main camera that will fill the box with lots of instances of the prefab and give them a velocity in a random direction.
using UnityEngine;
public class Atmosphere : MonoBehaviour
{
public GameObject Molecule;
void Start()
{
float x = -4.5f;
while (x < 4.5f)
{
float y = -4.5f;
while (y < 4.5f)
{
var inst = GameObject.Instantiate(Molecule);
inst.transform.position = new Vector3(x, y, 0);
var rb = inst.GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
rb.AddForce(new Vector2(xForce, yForce) * 100f);
y += 0.5f;
}
x += 0.5f;
}
}
}
For a while the dots bounce around against each other and the edges of the box.
But after a while they eventually get stuck to the edges of the box.
Both the box and balls and the box walls have the same physics material
Which has zero friction and a bounciness of 1.
Why do they stick to the walls, and how can I stop it from happening?
Download Unity 3D demo
UPDATE
If I drop a single molecule into the box with the following script attached it gets stuck to the wall immediately.
[RequireComponent(typeof(Rigidbody2D))]
public class Molecule : MonoBehaviour
{
Rigidbody2D RigidBody2D;
void Start()
{
transform.position = new Vector3(0, 1, 0);
RigidBody2D = GetComponent<Rigidbody2D>();
float xForce = Random.value * 2f - 1f;
float yForce = Random.value * 2f - 1f;
RigidBody2D.AddForce(new Vector2(-.25f, -0.25f) * 100f);
}
}
Unity3D has a velocity threshold. Objects with a velocity below this threshold won't bounce etc.
The solution is to go to Edit > Project Settings > Physics 2D and to set the Velocity Threshold lower.
EDIT - The real solution:
So I was doing some reading on integration techniques and it hit me: The energy you're losing is quite likely coming from numerical inaccuracies stemming from several approximation techniques compounded.
I'm guessing the continuous collision detection algorithm is mostly to blame, floating-point error accumulation, but probably also from numerical integration techniques.
What you're trying to achieve is elastic collision, which means that it satisfies conservation of energy as well as momentum. The trick is going to be for you to add a script to every object that preserves the energy of the system by adding error-correcting velocity over time. Whether you actually use the energy route or not is up to you, there are a number of ways to track and modify the energy resulting in a change of velocity. Momentum would be the would be the easiest to track in my opinion. What you're trying to achieve is elastic collision, which means that it satisfies conservation
i.e.
Make a component that preserves the scalar quantity of kinetic energy or momentum (it'll probably produce the same results)
When you initialize all the particles with a velocity, make sure to save the starting momentum in the particle's script. I would save the scalar quantity for simplicity, so just use the length of velocity
Every frame, in the update event check the velocity of the rigid body. Find the change in momentum or change in energy and add the -difference and apply it to the object.
I doubt you'll have to work on collision events as well, especially if you use the exact same mass for every object. Here's a link with an example where someone corrected unity's friction-less physics using conservation of energy https://answers.unity.com/questions/168393/frictionless-physics.html
colliders may be stuck in each other for the reason of low contact offset, go to edit-project settings-physics2d and increase the default contact offset a little bit, 0.12 for example, it was work for me.
cheers

Rigidbody.Moveposition issue

I'm trying to make a type of projectile with Rigidbody:
private void FiredAsProjectile(GameObject target)
{
Vector3 moveVector = Vector3.Zero;
float velMod = 8f // A placeholder value to later calculate with mass / velocity
if(target != null)
{
moveVector = (target.transform.position - transform.position);
m_rb.MovePosition(transform.position + moveVector * Time.deltaTime * velMod);
}
}
This is updated via FixedUpdate upon calling this method somewhere else. I have a few things I needed this to behave: to have velocity output and move to a position, not direction.
However, I'm getting a weird outcome. Even though this object moves as a kinematic rigidbody and its interpolation is set to None this object slows down before reaching the target vector as if it has interpolation. Let's say I wanted a bullet to be fired from the barrel and fly to a point in world instead of direction, that's what I wanted this object to behave like, but not quite so.
Am I missing something or misunderstanding something?
Is there a better way to move this kinematic rigidbody whilst still outputting rigidbody.velocity and still collide?
This happens because you don't Normalize the moveVector.
To explain why this happens, we'll suppose that Time.deltaTime = 0.01 every step:
At t0 time, let's say that the distance between the moving object (in x = 0) and the target object (x = 100) is 100.
The argument of MovePosition is 0 + 100*8*.01 = 8 and the object is moved accordingly to this new position (since you said it's Kinematic without interpolation)
At t1 time, moveVector = 100-8 = 92
The new argument now is 8 + 92*8*.01 = 15.36
Notice that between t0 and t1 you moved 8 units, whereas between t1 and t2 you moved only 7.36 units. So, the more your moving object is near the target object, the less you'll move the object, giving the effect of "slowing down" (and moreover it'll never reach the target object, you'll stop at a distance equal to the minimum floating number precision).
In order to fix this, you just need to normalize the moveVector, i.e. making its module fixed every step. So, just add this line:
moveVector = (target.transform.position - transform.position);
moveVector.Normalize();
m_rb.MovePosition(transform.position + moveVector * Time.deltaTime * velMod);
and the distance moved every step will always be the same regardless of distance.

Add a constant force in Unity2D

I have a ball and I want to move it on the X axis, so, in the FixedUpdate method I added a force:
rigidbody2D.AddForce(Vector2.right * speed);
The ball's speed increases because of this code I wrote. I want to make this force to be constant, so the ball's speed not to increase. How can I do that? Thanks a lot!
Applying a constant force will accelerate the object, because that's how real physics work:
Force = mass * acceleration
In your case, the resulting acceleration is:
Acceleration = Force / mass
If you want to set the object speed to be constant, you should modify the rigidBody's velocity:
http://docs.unity3d.com/ScriptReference/Rigidbody2D-velocity.html
Something like this:
rigidbody2D.velocity = new Vector2(speed, 0);