So I’m trying to achieve the same effect that launching plants achieve in Plants versus Zombies. Where an object targets a moving enemy…get’s tossed in the air and eventually hits it’s target.
The hieght of the arc is dictated by the distance the object needs to travel to get to it’s target. At first I thought this was a slerp, but perhaps this is something else.
here’s a video showcasing the type of dynamic arch I’m trying to achieve.
My limited experience of a slerp has the speed the object travels varied to have it hit the target at the desired time. In the video, the speed is constant, and the arc of the object is adjusted to insure that the object hit’s the target at the desired time.
It wouldn’t take much to simulate the throw with some simple physics calculations, but for what is done in the video, I think a simple Sin() function will do the job. It is not only that the object is flying in an arc, but that the movement up/down under the influence of gravity need to look right. Here is a sample script. I’ve calculated the height as half of the distance traveled. You can adjust this for the specific feel of your throws. In looking at the video, it seemed that objects had a speed rather than a time. That is an object thrown from a further distance took more time. It was hard for me to tell. I’ve implement the code with speed, but you can just set ‘time’ to a fixed value if you want the object to travel in a fixed amount of time no matter what the distance. To test:
Create a new scene
Create a sphere at the origin
Scale the sphere down (0.4, 0.4 0,4)
Attach the following script
While running the app, click the left mouse button
var speed = 4.0;
private var lobbing = false;
function Lob(dest : Vector3) {
lobbing = true;
var start = transform.position;
var dist = (dest - transform.position).magnitude;
var height = 0.5 * dist;
var timer = 0.0;
var time = dist / speed;
var fraction = 0.0;
do {
fraction = timer / time;
var pos = Vector3.Lerp(start, dest, fraction);
pos.y += Mathf.Sin(Mathf.PI * fraction) * height;
transform.position = pos;
timer += Time.deltaTime;
yield;
} while (fraction < 1.0);
transform.position = dest;
lobbing = false;
}
function Update () {
if (!lobbing && Input.GetMouseButtonDown(0)) {
var pos = Input.mousePosition;
pos.z = 10;
pos = Camera.main.ScreenToWorldPoint(pos);
Lob(pos);
}
}
Im sorry this is in C# but that’s all i know in this depth, hopefully if you really cant use this someone can convert it for you.
If there is any part of this you don’t understand leave a comment and i will help as soon as i can
Maybe you would be better off with moving your objects along a bezier curve?
With one control point (position of which you can make slightly random and dependant upon the distance between shooter and the target) you can achieve a similar effect.