- Home /
Deviating from path while falling down.
My stone(gameobject) falls, I've attached the rigid body and ticked gravity. Since the speed of gravity is too low for my game, I've used
var forceValue: float = 10f;
.....
rigidbody.AddForce(-Vector3.up * forceValue);
While falling, the stone needs to deviate from its path when left/right arrow keys are pressed. tried
transform.position.x--;
for left arrow, and
transform.position.x++;
for right arrow.
What am I actually looking for, is that when an arrow is pressed the stone needs to move to extreme edge of the screen smoothly/rapidly with out any change in the speed of down fall.
Any suggestions?? Thanks in advance.
Answer by aldonaletto · Apr 22, 2012 at 05:32 PM
Precise positioning in physics is very complicated: you must write a PID controller to reach reasonably precise positions. Since your case is relatively simple - only X positioning - maybe a simple P (proportional) controller can do the job: you control the desired X coordinate with the keyboard (A or left arrow, D or right arrow) and the script tries to move the rigidbody there by controlling its velocity.x - an error is calculated and multiplied by a gain factor, and the result sets the X rigidbody velocity:
var xSpeed: float = 100; // control speed in x - units per second var vGain: float = 10; // P controller gain var maxVel: float = 100; // max P controller velocity
private var targetX: float;
function Start(){ targetX = transform.position.x; // initialize targetX }
function Update(){ // move targetX coordinate with the Horizontal axis: targetX += Input.GetAxis("Horizontal") xSpeed Time.deltaTime; }
function FixedUpdate(){ // add your extra gravity rigidbody.AddForce(-Vector3.up forceValue); // try to reach targetX by handling the rigidbody velocity. // calculate the difference targetX - current X position: var error = targetX - transform.position.x; // set velocity.x proportionally to the difference (clamp to maxVel): rigidbody.velocity.x = Mathf.Clamp(speed error, -maxVel, maxVel); } You may have to tweak the parameters vGain and maxVel: if the rigidbody becomes too slow closer to the desired position, increase vGain; if it passes the final position and starts oscillating around it, reduce vGain; maxVel clamps the maximum velocity - reduce it if the rigidbody oscillates madly, and increase it if the rigidbody goes too slowly to the target point.
EDITED: Well, making it go to the left or right positions when the arrow keys are pressed and return to center when they are released is easy in this script: you must save the initial center X coordinate and define the max excursions to left and right, then change Update to move targetX to the desired position when the keys are pressed, and set it to the center when they are released. You must tweak the variables maxLeft and maxRight to make the object reach the desired left and right limits;
var maxLeft: float = 10; // max excursion to left - adjust in the Inspector var maxRight: float = 10; // max excursion to right - adjust in the Inspector var xSpeed: float = 100; // control speed in x - units per second var vGain: float = 10; // P controller gain var maxVel: float = 100; // max P controller velocity
private var centerX: float; // initial object X coordinate private var targetX: float; // desired X coordinate
function Start(){ centerX = transform.position.x; // save center position in centerX... targetX = centerX; // and initialize targetX }
function Update(){ // move targetX with arrow keys: if (Input.GetKey("left")){ // left arrow: move left targetX = centerX - maxLeft; } else if (Input.GetKey("right"){ // right arrow: move right targetX = centerX + maxRight; } else { // nothing pressed: return to center targetX = centerX; } }
function FixedUpdate(){ // add your extra gravity rigidbody.AddForce(-Vector3.up forceValue); // try to reach targetX by handling the rigidbody velocity. // calculate the difference targetX - current X position: var error = targetX - transform.position.x; // set velocity.x proportionally to the difference (clamp to maxVel): rigidbody.velocity.x = Mathf.Clamp(speed error, -maxVel, maxVel); }
I don't think he needs so much precision, otherwise I would have proposed PID controller myself, I know these pretty well(lineleading in robotics. Noone has been able to beat our speed with that, if motors are about same(we do mostly Lego $$anonymous$$indStorms) and we don't screw the tuning up)
You're probably right in this case, but controlling rigidbody position with forces is still very complicated - when the input axis return to 0, the rigidbody continues moving and you must apply a counter force to make it stop (or set a big drag value, what would affect the vertical velocity). What I propose is actually a control of velocity with feedback - and after think a little more, even the feedback could be removed, and the input value could control directly the velocity - something like we do with the CharacterController.
Aldo, Thanks for the code. But what I actually was looking for was that in arrow key (left/right) button press the stone will move to the respective side and return back to the center position. Something like a falling stone(movement in y-axis) making a jump (in x-axis) and returning to 0th position in x-axis.
It's easy to modify this script to achieve this - take a look at my answer, which I edited to behave this way.
Aldo, will try this and roll back to you! By the way thanks for the help.
Answer by raoz · Apr 22, 2012 at 02:51 PM
use rigidbody.AddForce for left and right, too. And to cap it off, I suggest a simple if block.
Like, if you want to move it to the left of the screen and it has to move on x axis down until its x value is 100, than
if(transform.position.x > 100)
rigidbody.AddForce(new Vector3(speed, 0, 0));
This works. Thanks. The delay for the reply was that I was checking with Aldo's code. By the way can you suggest a way that can bring the stone back to zero in x- axis??
Answer by e-bonneville · Apr 22, 2012 at 03:16 PM
rigidbody.AddForce(new Vector3(Input.GetAxis("Horizontal") * speed, 0, 0));
Your answer
Follow this Question
Related Questions
Moving an Object to the vector of other objects on button press using a vector3 array? 0 Answers
How to Have Projectile Reset to Initial Position Relative to Parent 1 Answer
Movement with iTween and parameter 0 Answers
translate 2 Answers
Spaceship movement with acceleration and deceleration on Unity 0 Answers