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

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.

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).

How to make a model appear in front of AR Camera after the session starts using ARFoundation?

I was looking to update the ARcamera position.I am doing ImageTracking project.It detects an image and a corresponding prefab is shown in front of the camera.It starts playing an animation.After the animation I want the prefab to come really close towards the camera.When I give the code prefab.position=ARcamera.position; after animation code,I think the prefab goes to the initial position where the ARCamera was when the app had started that is (0,0,0).
How to make the prefab come really close towards the front camera.
speed = 10f;
float step = speed * Time.deltaTime;
Showprefabs.transform.GetChild(0).position = Vector3.MoveTowards(Showprefabs.transform.GetChild(0).position,
new Vector3(Arcam.transform.position.x, Arcam.transform.position.y + 0.2f,
Arcam.transform.position.z + 6.3f), step);
//The values 0.2f and 6.3f I added using the Editor to make the prefab come near the camera(But in world position it is different.)
First of all I hope by "prefab" you mean already Instantiated GameObject. It makes no sense to move a prefab ;)
You tried to calculate the target position but did it with World-Space coordinates.
You probably want to do something like
var targetObject = Showprefabs.transform.GetChild(0);
var currentPosition = targetObject.position;
var targetPosition = Arcam.transform.position
// Place it 60cm in front of the camera
+ Arcam.transform.forward * 0.6f
// additionally move it "up" 20cm perpendicular to the view direction
+ Arcam.transform.up * 0.2f;
targetObject.position = Vector3.MoveTowards(currentPosition, targetPosition, step * Time.deltaTime);
If you want that movement a bit smoother so it moves slower if already close and faster if further away you might be interested in rather using Vector3.Lerp here
public float smoothFactor = 0.5f;
targetObject.position = Vector3.Lerp(currentPosition, targetPosition, smoothFactor);
Where a smoothFactor of 0.5 reads: Every frame set the object to a position in the center of the currentPosition and targetPosition. A value closer to 0 results in slower movement, closer to 1 in faster reaching the targetPosition.
Note that actually this approach will never really fully arrive at the targetPosition but only come very very close but usually this doesn't matter in AR where the Camera constantly moves a bit anyway.

How to add inertia to object 3d in Unity?

I create a game and I need use inertia for object.
Example:
The image shows all what I need.
When I touch on screen, blueObject no longer uses the position of brownObject and rotation of redObject. And I add component Rigidbody. The object just falls down. I need him to fall further along his trajectory (inertia).
I tried to use addForce(transform.forward * float), this not work.
By setting the position of the transform, you don't use Unity Physics engine. Your cube must have a rigidbody from the begin of the simulation and what you need here is a spring joint (https://docs.unity3d.com/Manual/class-SpringJoint.html) or a fixed joint.
You need to calculate the current speed, when releasing the object.
Track the positions over the last frame & current frame, and use Time.deltaTime to compensate different frame-rates.
Then set this velocity to your objects rigidbody. (AddForce is just manipulating the velocity, but depending on the ForceMode it respects mass etc.)
public Vector3 lastPosition = Vector3.zero;
void Update()
{
// maybe do : if(lastPosition != Vector3.zero) to be sure
Vector3 obj_velocity = (lastPosition - transform.position) * Time.deltaTime;
lastPosition = transform.position;
// if you release the object, do your thing, add rigidbody, then:
rb.velocity = obj_velocity;
}
That should create the "inertia". the velocity contains the direction and the speed.

JScript -- Unity transform.eulerAngles.y not Working

So last week I started working on an RPG and I've started working on the enemy AI and it should rotate to it's target but it doesn't. What I did is for the enemy I created a child object and put a script that rotates it to the target, then in the enemy script I did this:
if(transform.eulerAngles.y > rotTracker.transform.eulerAngles.y) {
transform.eulerAngles.y -= 2 * Time.deltaTime;
}
if(transform.eulerAngles.y < rotTracker.transform.eulerAngles.y) {
transform.eulerAngles.y += 2 * Time.deltaTime;
}
the rotTracker is a GameObject variable. So, what is wrong with this code? The rotation tracker changes rotations but not the enemy. Maybe because it has child objects that look at a different thing? I created a sprite and put it on top of the enemy and it represents the enemies health and always turns towards the camera.
You can't change directly the angles. You need to change the vector positions. For example:
var yRotation -= 2 * Time.deltaTime;
transform.eulerAngles = new Vector3(0, yRotation, 0);
Hope this helps!
You shouldn't use transform.eulerAngles for increment, only fixed values. Also, better set it as vector, not the single axis.
If you've put the the script on the child and actually want to rotate the parent, then you have the wrong transform, but I can't clearly read that.
Further on I'd recommend doing something like this:
var dir = transform.postion - target.position;
dir.y = 0; // set the axis you want to rotate around to 0
var targetRotation = Quaternion.LookRotation(dir);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRotation, Time.deltaTime * speed);
speed being a factor for how fast you want to rotate.
(I think the code should be correct, I'm using C# though.)

accelerated addforce for rigidbody

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.