Trying to display the velocity of a GameObject in Unity, numbers bouncing all over - unity3d

Ok I'm developing a game in which you land a rocket ship while avoiding asteroids... Pretty simple. I have two UI Text elements that are meant to display the current vertical and horizontal velocity. I searched around and came up empty in terms of unity having a built in function to get the current velocity of a 2D rigidbody so I came up with this:
void Update () {
shipVelocity = Mathf.Abs((lastPosition.y - spaceShip.transform.position.y) / Time.deltaTime);
shipAngularVelocity = Mathf.Abs((lastPosition.x - spaceShip.transform.position.x) / Time.deltaTime);
uiText = "Vertical Velocity: " + shipVelocity;
currentVelocityText.text = uiText;
uiText = "Horizontal Velocity: " + shipAngularVelocity;
currentAngularVelocityText.text = uiText;
lastPosition = spaceShip.transform.position;
}
Basically it just does your standard velocity = delta position / delta time but something is wrong. The numbers bounce all over the place and after the ship has landed and is completely stationary the numbers still bounce around from 0-1. While it's flying the numbers rapidly change from what I think is an accurate velocity to 0 and back - so fast it basically just looks like it's blinking.
Could it be it's just calling it too fast? I.e. frame rate too high? If so how can I slow it down?
Thnx!

If you are updating a Rigidbody, it is important to put your update logic in "FixedUpdate()". This version of update is called at a set rate (default 50x/sec) and therefore should be used for updating physics logic. Link: https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html
This is common in games as it separates the framerate (draws/sec) from the update logic (updates/sec), meaning that of the framerate drops, the games underlying physics are not altered.

Related

Unity: Calculate angular velocity of rigidbody to always face specific direction

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.

Set maximum horizontal movement speed in Unity 2D without setting a maximum velocity

I've been looking around the Internet to help set my character's speed to a maximum - basically, putting an upper limit on its horizontal speed. The best thing I've found so far is this:
rb.velocity = new Vector2(Mathf.Clamp(rb.velocity.x, -maxSpeed, maxSpeed), rb.velocity.y);
The main issue with this, though, is that this prevents the character's actual velocity from going past whatever maxSpeed is set to (let's say 4), meaning that if, say, it is hit by a moving object that would push it so that its horizontal velocity would go past 4, whenever movement calculations are done, it would be reset to 4. What I am looking for is something that would prevent the character from accelerating on its own past 4 but that would still allow it to move with external force.
My idea would be to only clamp where you want to actively set the velocity due to user input and if it is not already higher (due to external forces).
something like
if(Mathf.Abs(rb.velocity.x) < maxSpeed)
{
// calculate your new velocity according to user input
float newVelX = XYZ;
// than clamp it
newVelX = Mathf.Clamp(newVelX, -maxSpeed, maxSpeed);
// and finally asign the new vel
rb.velocity = new Vector2(newVelX, rb.velocity.y);
}

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.

Ball is jumping unexpectedly in unity 3d

I'm making a game with unity3D that ball is rolling on the ground.
When I set single large ground block, and using Rigidbody.AddForce() in Unity3D. ball is rolling fine.
But if I set multiple small ground blocks, ball is jumping unexpectly on boundary of blocks. Even block size, positions and intervals are exactly matched.
Can I solve this problem?
(I can't freeze position Y of ball. because ball needs gravity.)
-edited-
Here is my code to move ball by AddForce(). when I clicked.
private void MoveBall(Vector3 pos)
{
Ray HookRay = Camera.main.ScreenPointToRay(pos);
int layerMask = LayerMask.GetMask("Block");
RaycastHit objectHit;
float distance = Mathf.Infinity;
if (Physics.Raycast(HookRay, out objectHit, distance, layerMask))
{
moveTo = objectHit.point;
Vector3 forceValue = moveTo - transform.position;
forceValue.y = 0f;
rb.AddForce( forceValue * charSpeed, ForceMode.Impulse);
}
}
And here is screenshot of Unity3D
I placed 3x1x3 cube blocks and arranged all positions Y to 0.
There are no cracks or gaps on it.
This likely comes from inaccuracies in the physics engine. They are there because the engine tries to cut corners to speed up processing. You can make it cut less counters (at the cost of speed) by following a few steps. First thing to try is to make the rigidbody do collision detection continuous. You can also try turning on interpolation. There are also more advanced ways where you will do physics updates more often than your frame rate. But I would try the simpler options first. They’re often enough.
Go to Edit -> Project Settings -> Physics and play with default contact offset, maybe make it much smaller like 0.00001 and try it. Another way you can freeze the y and then when some condition happens you can unfreeze it again.

Projectile Motion in Unity

So my friend and I are making some 2D game, we are using some custom character controller, so we are not using rigidbody2D. Now we have some sort of catapult which needs to eject the player in a projectile-motion style.
We've done it for the catapult which shoots the player straight up
In inspector you can decide how much units do you want player to jump and how much does it need to get to reach max height.
So here is the code for the catapult that shoots the player up.
float ejectInicialY = (jumpHeight - ( player.physics.gravity * Mathf.Pow(timeToReachMaxHeight, 2) / 2)) / timeToReachMaxHeight;
float ejectVelocityY = ejectInicialY + player.physics.gravity * Time.deltaTime;
player.physics.playerVelocity = new Vector2(ejectVelocityY, 0f);
I tried to apply the same formulas for the X coordinate, but it doesn't work well.
Any help would be greatly appreciated.
This is ultimately a physics problem.
You are calculating current velocities by determining the acceleration of the object. Acceleration of an object can be determined from the net force acting on the object (F) and the mass of the object (m) through the formula a = F / m. I highly recommend reading some explanations of projectile motion and understanding the meaning of the motion equations you are using.
Vertical Direction
For the vertical direction, the net vertical force during the jump (assuming no air drag, etc.) is player.physics.gravity. So you apply your motion formulas assuming a constant acceleration of player.physics.gravity, which you've seemed to have accomplished already.
Horizontal Direction
Becausegravity does not commonly act in the horizontal direction, the net horizontal force during the jump (assuming no air drag, etc.) is 0. So again you can apply your motion formulas, but this time using 0 as your acceleration. By doing this, you should realize that velocityX does not change (in the absence of net horizontal force). Therefore the X coordinate can be determined through (in pseudo-code) newPositionX = startPositionX + Time.deltaTime * velocityX