Projectile launch insufficient velocity

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:

  1. Make a cube with this script on it.
  2. Make another cube as a child. (no
    collider)
  3. Set the child as the “barrel” var.
  4. Set the maxRange variable to desired
    maximum range.
  5. Set any object (at about the same height) as a target
  6. 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--;
    		}
    }

I’m not seeing an error in your math, so I’m forced to guess that any discrepancy is the result of integration errors. Not sure what integration method unity uses for it’s physics calculations, but it will be based on updating every physics timestep, while the function you’re using is the “perfect” prediction.

First, make sure you’ve got drag set to 0 in the projectile prefab’s rigidbody settings; it’s 0 by default, so the rest of this post assumes it was already off and you’re still off the expected mark.

If that wasn’t the problem, two possible ways to deal with this come to mind: first, and easiest, you could shorten the physics timestep; the smaller the steps, the more closely the resulting trajectory will correspond to the “perfect” mathematical trajectory. This will come with a performance hit, how much of one depending on how much is going on in the scene, but if the scenes are relatively simple, physics-wise, it might not be a problem.

Alternately, you could NOT use the physics system at all. Instead, write an update function for your projectile that solves the trajectory function for the current absolute time T every frame. This will be more expensive for the projectiles themselves, but won’t have the same increased cost for all rigid bodies in the scene like shortening the timestep might. For how to write the update function, see this article which works through the math for setting up the functions based on initial position, velocity, and angle.

Good luck, hope this helps!

Aha found it. ty anyway, sounds like good advise.

i tried some more extreme ranges and noticed eventually that even though the projuctile was rotated the right way that it wasnt actually ever traveling up at all, just faster forwards.
I figured out it had been given the actual launch direction of the launcher base but not the barrel, which fooled me for awhile because the left-right direction would still be correct and the projectile still got some distance.

Now the thing is DEADLY, the only way to escape is to keep moving, get under the barrel, or run out of its range.

in the fire() function this is the correct code

instantiatedProjectile.velocity=barrel.transform.TransformDirection(Vector3(0,0,speed));