Projectile calculations in 3D space, using your own movement code

It’s been a while 🙂 I have been busy and did not have the energy to finish this 4 part series of projectile calculations. Now I am finally putting out the last bit. Calculating the projectile movement in 3D space using your own movement code.

For starters, lets refresh what I wanted to write in the first place. I was working with a project where I needed to calculate the a projectile path in 3D space using my own movement code rather than relying on the rigid body and physic engine. In my case I absolutely wanted the projectile to hit the target always so I couldn’t go with the calculate path with any given velocity and any given angle.

For a refreshment’s sake, let’s revisit this picture. Red diamond is the source and green cube is the target. Source position is x1, y1, z1 and target position is x2, y2, z2. The angle between x -axis and projectile is theta which is 66 degrees in the example. Y axis is up and Z is forward.

projectile_3d_001

So last time we used rigid body and it’s AddForce method to do all the work. Now we need to calculate the position by ourselves. So lets start with the same formula based on Wikipedia. You can solve the velocity from distance formula when both start and end y coordinates are 0. v = 1 / cos(a) * sqrt((0.5 * g * d * d) / (d * tan(a))); where v = velocity, d = distance, g = gravity and a = angle.

Since we are interested in horizontal velocity having 2 components (X and Z) and vertical component Y we need also calculate direction because we want to manipulate the X and Z correctly. Direction we can get by subtracting the start and end positions and taking the normalized of resulting vector. So: Vector3 direction = (end – start).normalized;

You are also going to need the duration the projectile will stay in the air. Well, you could also not care about this but probably you want to do some cleanup code so your scene will not get filled with projectiles that are already landed and immobile. You can use the horizontal distance as base for duration or you can use the Y component thus velocity and gravity. Since we used the horizontal distance last time let’s now use the Y component. So the duration can be calculated by: (Sin(Angle) * velocity * 2) / gravity.

So in our example: d = 21.2132, a = 66.0, g = 9.81, replacing the variables in the velocity equation give us v = 16.74. Duration is: 3.11

If you remember from the 2D example we used the Unity’s update() function to move the projectile. This is perfect fit again since we have just one more component it’s basically the same.

So we are going to utilize the Time.deltaTime so we know how long as time passed since last update and multiply that with horizontal velocity. This is going to be our fraction of the journey up to the destination in horizontal space. Then we need to multiply the (horizontal) speed with the fraction multiplied by direction. So code is:


var horizontal = Mathf.Cos(Angle * Mathf.Deg2Rad) * velocity;
float frac = (Time.deltaTime * horizontal / distance);
var direction = (target.transform.position - start).normalized;
float x = frac * distance * direction.x;
float z = frac * distance * direction.z;

I am actually doing unnecessarily the direction inside the Update() since start and end do not change during the projectile flight. Anyways. This is the increment / decrement you need to apply to X and Z components.

What about the Y component? This is exactly the same as previously. From the wikipedia article, height at arbitrary distance X: By feeding our parameters in the formula: height y = start.y + x * tan(angle) – (gravity * pow(x) / 2 * pow((velocity * cos(angle)))). Note: x here is the distance from the start. Well, wikipedia article is 2D so X is the distance from the start but we need to use both X and Z components. Well we actually have all we need, we did the fraction right?


Vector2 position = new Vector2(transform.position.x + x, transform.position.z + z);

This is the current projectile position and since I am using the code in the projectile, transform refers to this GameObject’s transform. If we take the position.magnitude we have the distance.

Ultimately we want to do this:


this.transform.position = new Vector3(position.x, y, position.y);

Note: We projected the X,Z movement to Vector2 so it do not have Z we need to use Y. You can do this also without the Vector2 by calculating the distance by:
sqrt(pow(start.x – end.x) + pow(start.z – end.z)).

So here it is, now you can do the projectile calculation in 3D by using your own code. The complete solutions is not here, but all the relevant bits are here so you should be able to complete the Update() function very easily.

What do you think of all this? Do you have any suggestions or feedback. Please leave a comment and happy coding!

Projectile calculations in 3D space, using rigid bodies

If you have been following what I wanted to write regarding projectile calculations you know now how to do the calculations in 2D with using both rigid bodies and by calculating the movement code yourself. Now we add one dimension and see how it effects things.

Let’s take a look at this picture. This is pretty similar than the previous one but with one more axis involved. This is your game where you have source (red diamond) and target (green cube). Source position is x1, y1, z1 and target position is x2, y2, z2. The angle between x -axis and projectile is theta which is 66 degrees in the example. Notice how now Y axis is up and Z is forward.

projectile_3d_001

We are still going to need the velocity vector like previously which then can be applied to rigid body. You have now three components X, Y and Z that you need to solve because you want the projectile to move to all directions.

With the same formula based on Wikipedia you can solve the velocity from distance formula when both start and end y coordinates are 0. v = 1 / cos(a) * sqrt((0.5 * g * d * d) / (d * tan(a))); where v = velocity, d = distance, g = gravity and a = angle.

Since we are now interested in horizontal velocity having 2 components (X and Z) and vertical component Y we need also calculate direction because that is going to dictate how much force we need per component. Direction we can get by subtracting the start and end positions and taking the normalized of resulting vector. So: Vector3 direction = (end – start).normalized;

Distance you get by d = sqrt(pow((x2 – x1)) + pow(y2 – y1)), or Vector3.Distance(start, end) or (start,end).magnitude (where start and end are Vector3 objects)

So in our example: d = 21.2132, a = 66.0, g = 9.81, replacing the variables in the equation give us v = 15.0929.

Remember how we used the rigid body’s AddForce -method to apply the velocity vector? We can use the same function but now we are going to need the Z -component too. Last time we did this:


var distance = Vector3.Distance(target.transform.position, position);
var velocity = (float)(1 / Mathf.Cos(angle * Mathf.Deg2Rad)) * Mathf.Sqrt((float)(0.5f * 9.81 * distance * distance) / (distance * Mathf.Tan(angle * Mathf.Deg2Rad)));
float horizontal = Mathf.Cos(angle * Mathf.Deg2Rad) * velocity;
var direction = (target.transform.position - position).normalized;
var rbVelocity = new Vector2(direction.x * horizontal, Mathf.Sin(angle * Mathf.Deg2Rad) * velocity);
rigidBody.AddForce(rbVelocity, ForceMode.Impulse);

Now we just use Vector3 like this:


var rbVelocity = new Vector3(direction.x * horizontal, Mathf.Sin(angle * Mathf.Deg2Rad) * velocity, direction.z * horizontal);

That is basically all we need. Adding the third dimension was very easy since the direction already contains both X and Z components that we need. Now you can fire a projectile that will always land on it target so matter what is used angle (with the exception of 90 and 0 of course). What do you think, any ideas or suggestions? Please, leave a comment.

Simple projectile calculations in 2D with your own movement code

So last time we did a simple projectile calculation by using Unity’s rigid bodies by calculating velocity vector and applying a force to the projectile rigid body. Now we do the same without rigid body but doing a calculation based on updating the position manually.

Remember this was the sketch of what we have:

projectile_2d_001

For updating the position we need to know the angle, distance, amount of gravity and time of flight. We also need to calculate the velocity which we need to do other calculations. The distance as you remember from the last time we get by: d = sqrt(pow((x2 – x1)) + pow(y2 – y1)), or Vector3.Distance(start, end) or (start,end).magnitude (where start and end are Vector3 objects).

So in our example: d = 15.0, a = 66.0, g = 9.81, replacing the variables in the equation give us v = 14.0716. Now we are interested how long the projectile will stay in the air. This is because we need to interpolate the position between the start and end positions. We could use some a fixed value for time but this will create unrealistic result since the actual time spent in the air depends on the angle and distance (and gravity).

So how we get the time? You can calculate the time the projectile is airborn in two ways. Either you can use the Y component (eventually gravity pulls the projectile back to ground) or X component. If you want to use Y, the formula is time t = (velocityY * 2) / gravity. So y velocity times 2 over gravity. If you remember from the last time we used the velocity and direction to get the horizontal velocity and sin(angle) * velocity to get Y vertical velocity? We use the same method like this:


var direction = (target.transform.position - start).normalized;
var horizontal = Mathf.Cos(angle * Mathf.Deg2Rad) * velocity;
var vertical = Mathf.Sin(angle * Mathf.Deg2Rad) * velocity;

Finally we can calculate time: t = (vertical * 2) / g. So in our example it is: 2.62s This means that the projectile will stay in the air 2.62 seconds without hitting the target. So bigger the angle more velocity we need to hit the target thus longer the projectile will stay in the air. You could also use t = distance / horizontal, which by the way also gives the same 2.62. (which is a good thing!)

Ok, we have now all the components needed for our calculation. We are using Update() function which Unity will call every frame. This makes the function frame rate dependent, e.g. with 30 fps Update will get called on average by every 33.33 ms. So we know that we should get from start to the end in 2.62s. I said we need to interpolate the position based on the time. This can be done in several ways.

Unity has a Vector3.Lerp -function what is very handy what we can use e.q. Vector3 currentPos = Vector3.Lerp(start, end, time / duration); If the use this helper inside Update() -function we need to increment time variable by the difference of the previous call and Time.deltaTime is exactly for this. This way you make sure your stuff is not frame rate dependent. So a small example:

private float time = 0.0f;

private void Update()
{
time+=Time.deltaTime;
var currenPos = Vector3.Lerp(start, end, time/duration);
}

Duration you need to be calculate somewhere outside Update and start and end are positions as Vector3 type.

If you update your projectile currentPos, it will fly from start to end in given duration, but since it’s a linear interpolation between the values it do not have the projectile trajectory yet. We actually use only the x component to update the x position but we also use it to calculate y position. So how it’s calculated? We go back to the original Wikipedia page and see that height at arbitrary distance x has a formula:

height y = start.y + x * tan(angle) – (gravity * pow(x) / 2 * pow((velocity * cos(angle))))

so when in our Update() function we apply the x from current position to the formula, we have the height at distance x. The update function is going to need something more than that, for example you don’t want to update the position unless the projectile has been launched and you don’t want to update the position after time > duration. But that’s easy stuff after all this.

Neat, now you can hit the target by any angle and distance and you are doing it all by yourself! What do you think? Do you have any suggestions or improvements? Leave comments!

Advertising in Facebook

ws_fb_gridtool001

This entry is about advertising in Facebook. Like my readers know I have created a word game called Word Slinger for Android. It’s published in Play Store and even though it was more like a learning project rather than a serious attempt to create something magical, I would like to see if other people enjoy the game and probably learn a bit more what could be improved.

So for that purpose I need players and getting players is very difficult for an indie developer. This is something you will encounter always when you search how to get visibility and/or players. There are some sites that do reviews but some are utterly expensive and the free ones get massive amount of requests for reviews you need to be very lucky to get reviewed.

My brother and his colleagues created also a game and they utilized Facebook ads. Having heard about the positive experiences (combined with the earlier knowledge, thanks Milan) I decided to give a go.

I wanted to keep my expenses very low just to learn the mechanics and see how it goes. Creating an ad in FB is relatively easy. I say relatively because there are some things that can go wrong. It’s easy to select your target audience by selecting the country. This selection has the biggest influence on the suggested bid. Suggested bid is the amount of money you are willing to spend for certain action your targeting. To simplify this: If you want to get downloads for your app with fixed amount when any user clicks the ad then the max bid is what you are ready to pay for the click. It’s more complex than this but for simplicity I leave it here.

There’s a catch too. If you set the bid too low you are competing against the other advertisers and your ad is never shown if the bid is too low. I have run so few campaigns so far that I have just used the suggested minimum bid as my max bid. Occasionally this is enough but sometimes you need to raise the max bid.

There are other criteria to be selected like age, sex, interests and so on which all effect on the amount target audience but also to the bid. I have decided to target those FB users that I feel are matching my possible player base. This would be something like people of certain age, interest to word games and so on.

You also need to select the ad images. The images are FB cover photo size (1200 x 627). If you are running a longer lasting campaign you probably should select several images so that images are rotated. This doesn’t prevent the same ad to be shown twice to same person but it reduces the chances. If frequency goes a lot more above 1.00 then you can think of adding another image.

The real challenge in my opinion comes with the image approval process. The images should comply with FB ad photo criteria which state that images should not contain more than 20% text. This is, well, interesting to say the least. When you create the ad, there’s an automated process that approves your images (at least what I know of). So even though your image might have more text it will get approved. The problems might come when your ad goes live and starts to deliver.

When the ad goes live it can get disapproved all the sudden, in the middle of campaign. I don’t know if this is done by a person or another process but this has happened to  me 4-5 times. While FB support is very friendly and willing to solve the issue this can be problematic because of time zone difference. You might have to wait up to 20 hours for the reply and you can basically say goodbye for a planned weekend campaign if you have targeted far east like I did.

My product is a word game and it contains a lot of words. I thought I would have to create some sort of ad without words in it but according to FB you can use screenshots from your product. This is good to know and luckily I have managed to create ads with the screenshots. There’s still one remaining issue. When ever I create a new ad with the same images they always get auto approved and when they start to deliver they get disapproved. The only thing I currently can do is to contact FB and wait for another day to get them manually approved.

It would certainly be very interesting to hear any similar experiences or solution to this problem. Please, share your thoughts and ideas with me!

Word Slinger released!!

So the day finally came. My game is released in Google Play Store. This is absolutely a great day!

Those who have been following my blog know that I am moving to France and I just wanted to get this done before I leave. I will be developing the game while in France but the this was more like a mental deadline that I wanted to achieve.

I was quite long looking for an appropriate background image to the play screen but I didn’t find one and specially I didn’t find any free ones. I sent few email to few artist but unfortunately I didn’t get any response. So I had to draw myself and I am pretty content with the outcome.

Here’s the final version of the play screen:

Image

So, what are you waiting for? If you are an Android phone or tablet owner, please, do me a favor and download, try and rate my game! Thank you!