I am making a canon in which the maximum range is set in the inspector and a target within that range is fired upon during the game. The canon must rotate to the right angle to account for gravity.
How it is suposed to work: at start assume 45deg angle and find speed needed to shoot the set maximum range. Now if a target is within that range we will be guaranteed enough power to hit it with barrel angle.
Its not finding enough power to hit maximum range and therefore anything in between.
I used this for the math and I’m pretty sure I scripted it right Projectile motion - Wikipedia
See for youself, setup is simple:
- Make a cube with this script on it.
- Make another cube as a child. (no
collider) - Set the child as the “barrel” var.
- Set the maxRange variable to desired
maximum range. - Set any object (at about the same height) as a target
- Set a rigidbody as "projectile
The code may appear a bit long at a 1second glance but it isnt really and I’ve commented it.
The speed and dist(how far target is) are just temporary as the script adjusts them.
Wanted to watch most variables so I didnt make them private.
var speed:float=10; //speed of projectile
var g = 9.81; //gravity
var dist:float = 200; //how far target is
var maxRange:float=200; //set your maximum range
var degrees:float; //launch angle in degrees
var rads:float; // radians
var currot:float=1; //how far we are rotated now
var rotspeed:int=1; //how fast we rotate the barrel
var turnspeed:int=10; //how fast base rotates
var target:Transform; //the target
var barrel:Transform; //part that aims vertically and bullets come out
var projectile : Rigidbody;
var reloadTime = 0.5;
var ammoCount = 20;
private var lastShot = -10.0;
function Start(){
//find speed needed to reach set maximum range at 45deg elevation
speed=Mathf.Sqrt(maxRange*g);
}
function Update () {
//aiming the base and range
if(target){
//change to local coordinates
var targetRelative = transform.InverseTransformPoint(target.transform.position);
//distance to target
var range=Vector3.Distance(transform.position,target.position);
//aiming the base and range
if(range<maxRange){
//distance to shoot is equal to how far away target is
dist=range;
if (targetRelative.x > .004)
transform.Rotate(0,turnspeed * Time.deltaTime,0);
if(targetRelative.x < -.004)
transform.Rotate(0,turnspeed * Time.deltaTime*-1,0);
}
}
//math to find angle needed to hit a target within maximum range
rads=.5*(Mathf.Asin((dist*g)/(speed*speed)));
degrees=rads*Mathf.Rad2Deg; //conversion to degrees
//rotate the barrel to the degrees needed
if(currot<degrees-.2){
barrel.transform.Rotate(Vector3.right*Time.deltaTime*rotspeed*-1);
currot=currot+rotspeed*Time.deltaTime;
}
else if(currot>degrees+.2){
barrel.transform.Rotate(Vector3.right*Time.deltaTime*rotspeed);
currot=currot-rotspeed*Time.deltaTime;
}
//fire when barrel is rotated
if(currot>degrees-.5&&currot<degrees+.5)
Fire();
}
//basically the rocket launcher from fps tutorial
function Fire(){
if (Time.time > reloadTime + lastShot && ammoCount > 0) {
// create a new projectile, use the same position and rotation as the Launcher.
var instantiatedProjectile:Rigidbody=Instantiate(projectile,barrel.transform.position,barrel.transform.rotation);
// Give it an initial forward velocity. The direction is along the z-axis of the missile launcher's transform.
instantiatedProjectile.velocity=transform.TransformDirection(Vector3(0,0,speed));
lastShot=Time.time;
ammoCount--;
}
}