Ball Isn't following Trajectory line : Unity3d

Hello Everyone,

I am working on projectile motion. Sometimes my ball does not follow the trajectory line.

Code is here :

#pragma strict
#pragma implicit
#pragma downcast 
var turret : Transform; 
var bulletPrefab : Transform;
private var plane : Plane;
private var power : float = 30;
private var gravity: float = 9.8;
public var distance : float = 1.0f;
public var  predictionLine : LineRenderer;
public var enablePrediction : boolean = true;
public var targetPoint : boolean = true;
var velocity : Vector3;


private var horizontalOffset : float = 0.0f;
private var  lob : float = 0.75f;
var bullet : Transform ;
	
function Awake ()
{
	plane = Plane(-Vector3.forward,turret.position);
	predictionLine.SetWidth(1.0f,1.0f);
	bullet = Instantiate(bulletPrefab, turret.position, turret.rotation);
}	
function Update () 
{ 
	var distanceToPlane : float;
	var hit : RaycastHit; 
    var ray = camera.ScreenPointToRay(Input.mousePosition);   
    var hitPoint : Vector3;
	
	if(plane.Raycast(ray,distanceToPlane))
	{
			hitPoint = ray.GetPoint(distanceToPlane);
			velocity = GetTrajectoryVelocity(turret.position, hitPoint, lob, Physics.gravity);	
			turret.up = velocity;
	}
	
//	if(Input.GetMouseButtonDown(0))
//	{
//		if(plane.Raycast(ray,distanceToPlane))
//		{
//			GameObject.Find("SoccerBall(Clone)").transform.position = turret.position;
//			FireProjectile();
//		}
//	} 
	

	horizontalOffset = Mathf.Clamp(horizontalOffset, -45.0f, 35.0f);
		
	lob += Input.GetAxis("Mouse ScrollWheel") * 0.01f;
	//Debug.Log("lob" + lob);
	lob = Mathf.Clamp(lob, 0.25f, 1.2f);
	
	distance = Mathf.Clamp(distance, 0.25f, 1.5f);

	UpdatePredictionLine();  
		
	if (Input.touchCount > 0) {
		var touch = Input.GetTouch(0);
		
		switch (touch.phase) {
		
		case TouchPhase.Began:
			UpdatePredictionLine();  
			break;
		
		case TouchPhase.Moved:
			UpdatePredictionLine();  
			break;
			
		case TouchPhase.Ended:
			GameObject.Find("SoccerBall(Clone)").transform.position = turret.position;
			UpdatePredictionLine();  
			FireProjectile();
			break;
		   }
	    }
    }

	
        function UpdatePredictionLine() 
    	{
    		predictionLine.SetVertexCount(180);
    		var previousPosition : Vector3 = turret.position;
    		for(var i : int = 0; i < 180; i++)
    		{
    			var currentPosition : Vector3 = GetTrajectoryPoint(turret.position, velocity, i, 1, Physics.gravity);
    			var direction : Vector3= currentPosition - previousPosition;
    			direction.Normalize();
    			
    			var distance : float = Vector3.Distance(currentPosition, previousPosition);
    			
    			var hitInfo : RaycastHit ;
    			if(Physics.Raycast(previousPosition, direction,  hitInfo, distance))
    			{
    				predictionLine.SetPosition(i,hitInfo.point);
    				predictionLine.SetVertexCount(i);
    				break;
    			}
    			
    			previousPosition = currentPosition;
    			predictionLine.SetPosition(i,currentPosition);
    		}
    	}
    	
    	function GetTrajectoryPoint( startingPosition : Vector3 ,  initialVelocity : Vector3 ,  timestep : float,  lob : float ,  gravity : Vector3) : Vector3
    	{
        	var physicsTimestep : float = Time.fixedDeltaTime;
        	var stepVelocity : Vector3 = initialVelocity * physicsTimestep;
    		
    		//Gravity is already in meters per second, so we need meters per second per second
    		var stepGravity : Vector3 = gravity * physicsTimestep * physicsTimestep;
    		
    		return startingPosition + (timestep * stepVelocity) + ((( timestep * timestep + timestep) * stepGravity ) / 2.0f);
    	}
    	
    	function GetTrajectoryVelocity( startingPosition : Vector3,  targetPosition : Vector3,  lob : float ,  gravity : Vector3) : Vector3
    	{
    		var physicsTimestep : float = Time.fixedDeltaTime;
    	    var timestepsPerSecond : float = Mathf.Ceil(1f/physicsTimestep);
    		
    		//By default we set n so our projectile will reach our target point in 1 second
    	    var n : float = lob * timestepsPerSecond;
    		
    	    var a : Vector3 = physicsTimestep * physicsTimestep * gravity;
    		var p : Vector3 = targetPosition;
    		var s : Vector3 = startingPosition;
    	    
    		var velocity : Vector3 = (s + (((n * n + n) * a) / 2f) - p) * -1 / n;
    		//This will give us velocity per timestep. The physics engine expects velocity in terms of meters per second
    		velocity /= physicsTimestep;
    		return velocity;
    	}
    	
    	function FireProjectile() {
    		var rb : Rigidbody = GameObject.Find("SoccerBall(Clone)").GetComponent(Rigidbody);
    		rb.useGravity = true;
    		rb.transform.position = turret.position;
    		
    		rb.AddForce(velocity, ForceMode.Impulse);
    	} 

So what can be the reason? While touching it is changing the velocity?? I could not identify the bug.

It is specially happening with large angle.

Thanks in advance for your help and support…

In editor, use Input.GetKeyDown(Keycode.Mouse0) for TouchBegan Input.GetKey(Keycode.Mouse0) for TouchMove Input.GetKeyUp(Keycode.Mouse0) for TouchEnd and get the Logs for the values. You will find the problem on your own. And these GetKey methods will work same on devices too. No need to write separate code for touch events. For quick response come to [chatroom][1] [1]: http://chat.stackoverflow.com/rooms/37624/unity3d-developers

I have edited my question. It is behaving same way for mouse and touch input.

Still could not able to find the solution. Rigidbody force is not working for large angle.

why dont you try iTween for curved path??

1 Answer

1

You need to reset the velocity to zero before firing the bullet. For firing the bullet inside your FireProjectile() just add one line like following

function FireProjectile() 
    {
	    var rb : Rigidbody = GameObject.Find("Ball(Clone)").GetComponent(Rigidbody);
	    rb.useGravity = true;
	    rb.velocity=Vector2.zero;  //<=========== ADD THIS
	    rb.transform.position = turret.position;
	    rb.AddForce(velocity, ForceMode.Impulse);
    } 

Also for PC you can use this functions which will work on android / ios too.

                if(Input.GetKeyDown(KeyCode.Mouse0))
        	    {
        	    	 UpdatePredictionLine();
        	    }
        	    if(Input.GetKey(KeyCode.Mouse0))
        	    {
        	    	 UpdatePredictionLine();
        	    }
        	    if(Input.GetKeyUp(KeyCode.Mouse0))
        	    {
        	    	GameObject.Find("Ball(Clone)").transform.position = turret.position;
        			UpdatePredictionLine();
        			FireProjectile();
        	    }