New Scripter - Need Help Drawing Trajectory

Hello,

I’m a designer by trade but really want to be able to learn scripting to prototype ideas. This is my first time properly delving in to Unity! I’ve been using the Unity reference manual and the forums for help but I’ve hit a bit of a brick wall and was wondering if the community can offer some advice.

I have a small scene setup. Two pieces of terrain, a ball (player) and an orthographic camera. The player can click on the terrain to move to that position. They can click and hold on the player, drag back and release to “jump”. Think almost an Angry Birds catapult.

I would like to be able to draw the trajectory of the jump as the player is holding the mouse button down. I’ve found a formula for working out trajectory…

http://www.mathisfunforum.com/viewtopic.php?id=1673

…and I want to create a sphere primitive at 0.5, 1, 1.5, 2, and 2.5 seconds of the projected trajectory. In my code, I’ve only tried it using 2 seconds as you’ll see. At the moment the spheres are drawing under the floor rather than the intended path. I’m not sure whether it’s my angle calculations or my horrible, horrible interpretation of the trajectory formula. Most likely both…

If anyone can offer some advice or guidance would be great. Also, as this is my first major stab at scripting, general code practice comments and suggestions are welcome. I’m proud I’ve got this far though and I’m really enjoying using Unity.

Thanks in advance.

Loupz

#pragma strict

//Access jump script
var jumpScript : PlayerJump;
var clickedPlayer : boolean = false;
var jumpStart : Vector3;
var jumpEnd : Vector3;
var jumpVector : Vector3;
var clickedTerrain : boolean = false;
var multiplier = 30;

//Position variables
private var clickedPosition : float;
var playerCurrentPos : Transform;

//Walk speed available in the editor
var playerWalkSpeed = 30;

//Bool checking if the player has finished moving
var finishedMoving : boolean = true;

//Threshold for turning off the bool
var movementThreshold : float;

//Trigger
var movementTrigger : Transform;

//Angle Debug
private var angle : float;
private var angle1 : Vector2;
private var angle2 : Vector2;
//Screen position to world variable
private var p : Vector3;

function Start () {

}

function Update () {

	//Mouse click on button down
	if(Input.GetMouseButtonDown(0)){
		playerCurrentPos.rigidbody.drag = 0;
		movementTrigger.collider.isTrigger = false;
		jumpStart = Input.mousePosition;
		//Raycast to get mouse click position
		var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
		var hit : RaycastHit;
		if (Physics.Raycast (ray, hit, 100)) {
    		clickedPosition = hit.point.x;
    		finishedMoving = false;
    		if (hit.transform.name == "Player"){
    			clickedPlayer = true;
    			//Debug.Log("I have clicked on the player");
    		}
    		else if (hit.transform.tag == "Terrain"){
    			clickedTerrain = true;
    			//Debug.Log("I have clicked on the terrain");
    			movementTrigger.collider.isTrigger = true;
    			var moveMovementTrigger : Vector3 = new Vector3(hit.point.x, hit.point.y+0.05, 0);
    			movementTrigger.transform.position = moveMovementTrigger;
    		}
    		else {
    			//Debug.Log("waiting for clicks");
    		}
		}
	}
	
	//waiting for mouse button to be lifted AND player initially clicked - FIRE!
	if (Input.GetMouseButtonUp(0)  clickedPlayer == true){
		playerCurrentPos.rigidbody.AddForce(jumpVector * multiplier, ForceMode.Impulse);
		clickedPlayer = false;
	}
	
	//Draw trajectory
	if (Input.GetMouseButton(0)){
		//Pull back position in screen space
		jumpEnd = Input.mousePosition;
		//Screen space to world space
		p = Camera.main.ScreenToWorldPoint (Vector3 (jumpEnd.x, jumpEnd.y, 12.7));
		//Try and detect angle
		angle1 = new Vector2(playerCurrentPos.transform.position.x, playerCurrentPos.transform.position.y);
		angle2 = new Vector2(p.x, p.y);
		angle = Vector3.Angle(angle1, angle2);
		//Debug.Log(angle);		
		//Draw vector
		Debug.DrawLine(playerCurrentPos.transform.position, p, Color.red, 40);
		//Work out jump vector
		jumpVector = playerCurrentPos.transform.position - p;
		//Trajectory of X
		var trajX = (jumpVector.x*multiplier) * 2 * (Mathf.Cos(angle));	
		//Trajectory of Y
		var trajY = ((jumpVector.y*multiplier) * 2 * (Mathf.Sin(angle))) - (0.5 * 9.81 * (2*2));
		var sphere : GameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
		sphere.transform.position = Vector3(trajX, trajY, 12.7);
	}
	
	//Check if player has stopped moving
	if (finishedMoving == false  clickedTerrain == true){
		MovePlayer();
	}
}

//Moves player by taking clicked position and finding the difference between actual position and transforming
function MovePlayer() {	
	if (playerCurrentPos.transform.position.x >= clickedPosition + movementThreshold  || playerCurrentPos.transform.position.x <= clickedPosition - movementThreshold){
		var playerMovement = clickedPosition - playerCurrentPos.transform.position.x; //movement amount is the difference between clicked position and current position	
		playerCurrentPos.rigidbody.velocity = Vector3(playerMovement*playerWalkSpeed*Time.deltaTime, 0, 0);
		//Debug.Log(playerCurrentPos.position);
	}
	else {
		finishedMoving = true;
		clickedPlayer = false;
		clickedTerrain = false;
		Debug.Log("end");
	}
}

I just read the post on the forums you supplied and there it says, that x = v * t * cos(O)
I think that means that you should use jumpVector.magnitude instead of just the x-veclocity.
Same goes for y. Not sure if im right but you should check that again.

Thanks for the response Arterie. I’ve tried what you’ve suggested but the balls are still being drawn under the floor. I’ve taken a screenshot. The red lines show my “click and drag” direction on the player. I’ve marked an “X” where I think I should be seeing the balls being drawn as well. I’m not sure what the other large red line is, I can only see that in scene view, not in the game.

I’m still having trouble with this. I’ve debugged through the formula and using the examples given on the website, I was able to achieve the same results. I then plugged in all my variables in place of the examples and it didn’t work. I’ve changed gravity to -9.81 instead of 9.81 which made the debug spheres draw above ground. I’ve also noticed that where the spheres draw, they seem to be opposite to what I’m trying to achieve. For example, pulling back slightly down and to the left of the player produces high spheres drawn on the left rather than a low sphere drawn in the opposite direction of the pull back.

I’m thinking it now has something to do with the velocity calculation? Any help is appreciated?

#pragma strict

//Access jump script
var jumpScript : PlayerJump;
var clickedPlayer : boolean = false;
var jumpStart : Vector3;
var jumpEnd : Vector3;
var jumpVector : Vector3;
var clickedTerrain : boolean = false;
var multiplier = 30;

//Position variables
private var clickedPosition : float;
var playerCurrentPos : Transform;

//Walk speed available in the editor
var playerWalkSpeed = 30;

//Bool checking if the player has finished moving
var finishedMoving : boolean = true;

//Threshold for turning off the bool
var movementThreshold : float;

//Trigger
var movementTrigger : Transform;

//Angle Debug
private var angle : float;
private var angle1 : Vector2;
private var angle2 : Vector2;
private var jumpAngle : float;
//Screen position to world variable
private var p : Vector3;

function Start () {

}

function Update () {

	//Mouse click on button down
	if(Input.GetMouseButtonDown(0)){
		playerCurrentPos.rigidbody.drag = 0;
		movementTrigger.collider.isTrigger = false;
		jumpStart = Input.mousePosition;
		//Raycast to get mouse click position
		var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
		var hit : RaycastHit;
		if (Physics.Raycast (ray, hit, 100)) {
    		clickedPosition = hit.point.x;
    		finishedMoving = false;
    		if (hit.transform.name == "Player"){
    			clickedPlayer = true;
    			//Debug.Log("I have clicked on the player");
    		}
    		else if (hit.transform.tag == "Terrain"){
    			clickedTerrain = true;
    			//Debug.Log("I have clicked on the terrain");
    			movementTrigger.collider.isTrigger = true;
    			var moveMovementTrigger : Vector3 = new Vector3(hit.point.x, hit.point.y+0.05, 0);
    			movementTrigger.transform.position = moveMovementTrigger;
    		}
    		else {
    			//Debug.Log("waiting for clicks");
    		}
		}
	}
	
	//waiting for mouse button to be lifted AND player initially clicked - FIRE!
	if (Input.GetMouseButtonUp(0)  clickedPlayer == true){
		playerCurrentPos.rigidbody.AddForce(jumpVector * multiplier, ForceMode.Impulse);
		clickedPlayer = false;
	}
	
	//Draw trajectory
	if (Input.GetMouseButton(0)){
		//Pull back position in screen space
		jumpEnd = Input.mousePosition;
		//Screen space to world space
		p = Camera.main.ScreenToWorldPoint (Vector3 (jumpEnd.x, jumpEnd.y, 12.7));
		//Debug.Log(p);
		//Try and detect angle
		angle1 = (p - playerCurrentPos.transform.position);		
		angle2 = new Vector3(1, 0, 0);
		angle = Vector3.Angle(angle1, angle2);
		//turning angle into 360
		if (p.y <= playerCurrentPos.transform.position.y){
		jumpAngle = ((180 - angle) + 180) * Mathf.Deg2Rad;
		}
		else{
		jumpAngle = angle * Mathf.Deg2Rad;
		}
		//Test angle			
		//Debug.Log(jumpAngle);		
		//Draw vector
		Debug.DrawLine(playerCurrentPos.transform.position, p, Color.red, 40);
		//Work out jump vector
		jumpVector = playerCurrentPos.transform.position - p;
		//Trajectory of X
		var trajX = jumpVector.magnitude*multiplier * 2 * Mathf.Cos(jumpAngle);	
		//Trajectory of Y
		var trajY = (jumpVector.magnitude*multiplier * 2 * Mathf.Sin(jumpAngle)) - (0.5 * -9.81 * (2*2));
		//Debug.Log(trajY);
		var sphere : GameObject = GameObject.CreatePrimitive(PrimitiveType.Sphere);
		sphere.transform.position = Vector3(trajX, trajY, 0);
		Debug.Log(trajY);
	}
	
	//Check if player has stopped moving
	if (finishedMoving == false  clickedTerrain == true){
		MovePlayer();
	}
}

//Moves player by taking clicked position and finding the difference between actual position and transforming
function MovePlayer() {	
	if (playerCurrentPos.transform.position.x >= clickedPosition + movementThreshold  || playerCurrentPos.transform.position.x <= clickedPosition - movementThreshold){
		var playerMovement = clickedPosition - playerCurrentPos.transform.position.x; //movement amount is the difference between clicked position and current position	
		playerCurrentPos.rigidbody.velocity = Vector3(playerMovement*playerWalkSpeed*Time.deltaTime, 0, 0);
		//Debug.Log(playerCurrentPos.position);
	}
	else {
		finishedMoving = true;
		clickedPlayer = false;
		clickedTerrain = false;
		Debug.Log("end");
	}
}