- Home /
Setting limits to my trajectory
Hi, In my unity project I have a catapult that fires a block. So far I have made it so that after the catapult arm holding the block is rotated to a certain angle, it unchilds the block and makes it non-kinematic. I currently have it so it then applies a constant force to the z axis to speed it up. I also have it so that a force is applied in the y axis to bring it down to earth.
The problem is that I want it to do a typical trajectory curve. At the moment the problem is the z force reaches 10 and then an if statement decreases it and then because when it is decreased it no longer meets the criteria of that if statement it then increases then (effectively this causes it to balance out at a force of 9).
Another problem is that currently the y force only pulls the object down. I want it to rise and then fall.
The final problem is that I want the force to stop substantially when it hits another object.
Here is my current code that runs when the projectile is detached from the catapult object.
gameObject.tag = "projectile";
function Update () {
if(rigidbody.isKinematic == false) { if(constantForce.force.y >= -10) { gameObject.constantForce.force.y -= 0.1; }
if(constantForce.force.z <= 10 && constantForce.force.z >= 0)
{
gameObject.constantForce.force.z += 1;
}
if(constantForce.force.z == 10)
{
gameObject.constantForce.force.z -= 2;
}
} }
Answer by royce3 · Jan 10, 2012 at 01:55 PM
The rigidbody will already do everything you are trying to force it to. That's the point of setting isKinematic = false;
You might have to apply an initial force right at the point of releasing it from the catapult, but you shouldn't be applying one continually. The rigidbody's velocity and gravity will do the rest.
Once you have some sort of trajectory, you can tweak it by playing with the initial force applied and the rigidbody.mass
thanks I hadn't thought of that. I'll try your advice and let you know :)
Hi again, how do you add an initial force? I tried AddForce but it didn't seem to do anything.
AddForce should do it. $$anonymous$$ake sure is$$anonymous$$inematic=false, useGravity=true, and make sure the value you are passing to AddForce is large enough ( try larger numbers until you see a reaction )
Please clarify what you mean by "it keeps going", but I'll take some guesses at what you mean: If it just sails endlessly up into the air then you forgot to enable gravity in the rigidbody. If it's landing but keeps rolling then you might just need to increase the "Drag" and "Angular Drag" settings, or you could use isGrounded combined AddForce(-0.1 velocity time) to apply some ground-contact-friction.
Also, please accept my answer since your original problem has been solved, thanks.
AddForce tries to work like real physics and divides the force (in Newton's or something) by the weight. I find it easier to set the velocity directly. Gravity is 10m/s. So it's easy to figure out that velocity 0f 20 up will rise for two secs, then fall.
If you think you might change the weight of the rock (to give it more oomph when it hits,) then setting velocity is easier. If you might toss different objects, and want the catapult to fling light things faster, go with AddForce.
If your arm has y going up when it's flat, then arm.up
is the direction the rock should fly. Set rock.velocity = arm.up * 30.0f;
Answer by Owen-Reynolds · Jan 18, 2012 at 04:35 PM
You've got a lot of little issues here, too big to be answered in one question, but here are some topics:
Right now, you can use FindObjectsWithTag
to get the rock only if it's a regular gameObject. If you have it childed to the catapult arm (which will work better) you'll need to use transform.Find("rock")
. Or, if the rock is in the arm which is a child of the catapult body, then transform.Find("arm/rock");
.
The thing is, you won't be doing any of that for real. For real, you will be firing the rock and using rock=Instantiate(newRock, rockPos, ... );
to create another rock in the arm. You'll have your reference to the rock right there. rockPos will be a "mount point" -- an empty positioned where the rock should sit, childed to the arm. You'll find that using transform.Find("arm/rockPos");
After making the rock, you'll child it to the arm and freeze it: rock.parent=arm; rock.rigidbody.isKinematic=true;
.
The trick with rigidbodies is that you do nothing in the code. The rocks's Update/FixedUpdate will be empty. You can delete it. As a one-time thing in catapult, when the player hits the Fire key, you just say rock.rigidbody.isKinematic=false; rock.parent=null;
. That will cause the rock to drop to the ground, all by itself (funny thing -- if you forget to unchild it, it drops the same way, but also spins and moves with the catapult.) You resetting kinematic tells Unity that you want it to automatically move the rock.
To make it fly, also set velocity or do an Addforce to it -- also one time when you fire it. After that Unity will automatically handle movement, gravity, wind ... for you.
To check for a hit, you'll need to give the rock an OnCollisionEnter
function. Unity will automatically run this one time when it hits something. The examples in the docs for this show how to use CompareTag
to check whether you hit the ground or an enemy.
The good news is that lots of people have done various things like this. Just checking "catapult" gives two pages of questions.