Object maintains changes to its Y position after getting reset - unity3d

I have been programming a deeper version of Pong using skills.
One of the skills is that the player will make the other player's paddle stop, and instead the enemy will start moving its goal.
I start moving the goal with this method. The method is called in the FixedUpdate.
private void moveGoal(string vertical, Vector3 nextPosition)
{
nextPosition += speed * Time.fixedDeltaTime * Input.GetAxis(vertical) * Vector3.up;
nextPosition.y = Mathf.Clamp(nextPosition.y, goalMinY, goalMaxY);
rb.transform.position = nextPosition;
}
We have tried doing it in the Update and using the Time.deltaTime, but the result is the same.
We recently changed to "rb.transform.position" from "rb.MovePosition(nextPosition)" because the problem was way worse.
The position is reset with a method inside the skill's script where we have saved the base position of the goal, and once the skill gets deactivated it automatically reset the goal's position to its base position.
The problem is that if the goal starts in the Y position 1.4, after it has been reset the y position changes slightly, for example going from 1.4 to 1.25.
We do not understand why it is moving even though the position we set it to is always the same.
I am sorry if the post sounds confusing, but the problem itself is very confusing and very difficult to explain.

Sorry if I am misunderstanding your issue. Could it be that you reset the position of the goal but within the same frame it executes moveGoal() once, setting it slightly off your original position? Goodluck.

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.

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 object move toward a position with a overshot effect?

I'm trying to make an object moved to a position, but, depending on the speed it's going, I want it to overhoot it's target and bounce back to it.
This is how I'm moving the object toward the other now:
void FixedUpdate() {
transform.position = Vector2.Lerp (transform.position, blackhole.transform.position, Time.deltaTime * 25f);
}
This obviously doesn't account for the "overshoot" effect. However I've been having trouble to achieve it, since when trying with physics all my attempts end up with my object orbiting indefinitely around it's target, instead of passing it just once and moving inside it.
There are a few ways you could go about this. Nathan's suggestion of using "gravity" by applying forces every step I'll call the "Physics" solution. Your current solution that simply sets position I'll call the "Tweening" solution. Both can certainly work, and both can benefit from simply using if statements. For both solutions, stop the "orbiting" or head back from overShootPos with simple checks.
For Tweening:
When the move first starts, start tweening to a position past where you actually want to be.
Vector3 overShootPos = destinationPos + (destinationPos-transform.position)*overShootPercentage;
Then in FixedUpdate:
float deltaP = 0.001f;
if((transform.position-overShootPos).magnitude<deltaP){
//start tweening to destinationPos rather than overShootPos. Possibly just
overShootPos = destinationPos;
}
For Physics:
The forces actually will take the object past the destination, and it may start "orbiting" like you were saying.
In FixedUpdate, stop it once it's close and slow enough:
float deltaP = 1f; //may want larger delta here since physics is less precise.
if((transform.position-destinationPos).magnitude<deltaP && rb.velocity.magnitude<deltaP){
rb.velocity = Vector3.zero;
transform.position = destinationPos;
}
This is not all the code, but the basic idea should work.
Also, consider some of the differences between Physics and Tweening solutions (that may include code other than this). The Tweening will be very precise, and work basically the same way every time, where the Physics one may scale more crazily with large distances/fast speeds. The Physics solution is clearly needed if you do want the object to respond to explosions, collisions, etc.. on its route to the destination. If you go with Tweening, consider looking at tweening libraries like iTween and DOTween, especially if you'll be using a lot of tweens. They'll be faster (less Updates) and provide a nice syntax for doing stuff like this.
I would use a basic spring system. Equation of a spring
F = k(x-l) (Force = Spring Constant * (Extension - Rest Length)
So to calculate the spring force on your body:
Force = SpringConstant * (PointToHeadTo - CurrentPosition)
You then either use the physics damping in your engine or you apply your own damping
D = Velocity * -DampingConstant (DampingForce = Velocity * -DampingConstant)
Which you then apply as a force. However Unity / UE4 have damping co-efficients you set so you just need the spring force.
To keep things stable you can limit the Spring Force to a maximum and only have it take effect when within a radius of the target. You can also ramp up the damping as you cross the target to help bring it to rest.

Rigidbody Velocity Messing Up Physics UNITY

I am trying to move my player by using rigidbody.velocity:
rigidbod.velocity = new Vector2 (Input.GetAxis ("Horizontal") * maxSpeed, rigidbod.velocity.y);
the problem is, this messes up of my explosion code. The character is supposed to be knocked back when near an explosion. I know why it happens; if the player is still, the rigidbody's X velocity would be returned as 0, meaning any outside forces pushing the player along the X axis would counteract this. So when I add the explosion, the player cuts to his new position a few units away. It looks very unnatural and jerky, as he should be pushed back, but his code is telling him to be still unless a key is pressed. I'm posting this to see if there's any way I can re-write this code to be able to move the player while being pushed correctly from outside forces. I heard that AddForce works, but when I used it, my player's velocity constantly increased. He is wither way too fast or way too slow. Any ideas on how I can get this to work? I tried adding rigidbody.velocity.x after where it says 'maxspeed' hoping that it would allow outside force input, and it works, but it messes up the movement code, making him go way too fast. I can't seem to get both the explosions and the movement code to work correctly at the same time. Any help would be greatly appreciated. Thanks.
which is exactly why in the Unity docs they explicitly state:
In most cases you should not modify the velocity directly, as this can
result in unrealistic behaviour.
instead of modifying the velocity directly, you should be using an AddForce(..)
Vector2 force = new Vector2 (Input.GetAxis ("Horizontal") * maxSpeed, 0f);
rigidbody.AddForce(force);
//or if in update:
rigidbody.AddForce(force * Time.deltaTime);

How to smooth movement in Unity 4.3 2D with AddForce?

at the moment i'm working on a 2D plattformer and the work is going very well. But there is one Problem i can't get rid of.
The player can use a dash, which should move the player very fast in the direction he is looking. My problem is, that the player game object instant appears at the target location... like a teleport.
I'm using the AddForce Function to move the game object. On jumping i'm using AddForce as well and there it works really nice, i get a smooth jump movement.
The only different between dash and jump is that on jump i apply force to the y axis and on dash to the x axis. Changing the amount of force doesn't affect the movement only the distance.
Does anyone have an idea what i'm doing wrong?
// Dash
rigidbody2D.AddForce (new Vector2((dashSpeed * direction), 0));
// Jump
rigidbody2D.AddForce (new Vector2(0, jumpForce));
Best,
Verdemis :)
EDIT: I can not access my project at the moment, but i will try to show you what i have done.
Note: dashSpeed is a float value, at the moment something like 3500
and direction contains 1 or -1, depending on the direction the player is looking. The Dash code is part of the Update method.
// Dash
if(Input.GetKeyDown(dashKey))
rigidbody2D.AddForce (new Vector2((dashSpeed * direction), 0));
What is your direction vector, is it normalized? Since multiplying non-normalized vectors can be rather hazardous. Do you have more of the script to show?
EDIT: You should always do physics things in the FixedUpdate loop(link).
Ok i could solved the problem. My problem was that i only did this AddForce only once. The AddForce code was only executed in a single frame. I added a time which i count down to define how long the dash movement gonna be!
The problem may be that you are using a very big force, I was messing around with some physics today and realized that even a force of 100 almost looks instant. Try making a smaller force number to see if that helps you. I just tested making a smaller number and that does not work.