Shorten Raycast - Line Renderer

Hello,

I’m trying to shorten a line renderer, and I can’t for the life of me figure it out! I’m sure it’s an easy solution.

Basically, I have two line renderers, one coming from the player (which is a ball), if the player is facing another ball, the first line renderer is drawn between the player, and the other ball. A second line renderer is then draw from the other ball to wherever the balls force will go if I were to hit it… Pretty much like an aiming system you see in pool/billiard games.

All I want to do is shorten the second line renderer. Below is the code I’m using to calculate the second line direction:

var ballRadius = 0.49;
var contactPointSize = 0.1;
var rayLength : float = 30;
var direction = player.transform.TransformDirection(-Vector3.forward);

var hit : RaycastHit;
Physics.Raycast(transform.position, direction, hit, rayLength);
var newDirection = new Vector3();

newDirection = Vector3(hit.normal.x, hit.normal.y, hit.normal.z);
newDirection *= -1;
var hitPos = hit.collider.transform.position;

lineDirection.SetPosition(0, hit.collider.transform.position);

var deflection = Vector3((newDirection.x * rayLength), hitPos.y, (newDirection.z * rayLength));
var newDeflec = (hitPos + deflection) / 2;

lineDirection.SetPosition(1, deflection);

So lineDirection is the second line renderer, I want to always have its length at 5. I tried playing around with the maths, by adding hitPos and deflection, and then dividing by 2. That works fine - I get the middle of the raycast, but then when I try dividing it further, the coordinates go all messed up.

Also, I cant decrease the size the in ‘rayLength’ as then my Physics.Raycast wont shoot very far.

Any advice? Thanks.

PS, this is pretty much a repeat of a question I asked months ago, but never solved it:
http://answers.unity3d.com/questions/485577/linerenderer-setting-max-distance.html

here is a thought, you can use the “slope” (well in unity it easier to use an angle) of the line between those two to get a direction. then rotate Vector3.fwd*5 by that direction. Its basically aligning a shorter vector between the ball and hit target point.

  1. Get the Y-angle between the two points.
  2. Convert it to a Quaternion(man i hate these things)
  3. Multiply the product of Quaternion and the balls fwd vector by 5.
  4. use it in the Line Direction code.

so we can use

PSEUDO code
a = Vector3.Angle(ballPos, hitpos) 
and q = Quetrion.Euler (0,a,0);
lineDirection = q*ballpos.fwd*5;

this way the line direction will always have an “length” of 5.

citation : Visualization Tools for 3D

Quaternion - Wikipedia (again, I still hate these things)


Update: I overlooked some details, ported and tested you code and got it working

var ballRadius = 0.49;
var contactPointSize = 0.1;
var rayLength : float = 30;
var direction = player.transform.TransformDirection(-Vector3.forward);
 
var hit : RaycastHit;
Physics.Raycast(transform.position, direction, hit, rayLength);
var newDirection = new Vector3();
 
newDirection = Vector3(hit.normal.x, hit.normal.y, hit.normal.z);
newDirection *= -1;
var hitPos = hit.collider.transform.position;
 
lineDirection.SetPosition(0, hit.collider.transform.position);
 
var deflection = Vector3((newDirection.x * rayLength), hitPos.y, (newDirection.z * rayLength));
deflection = (deflection -hitPos).normalized * 5 + hitPos;
var newDeflec = (hitPos + deflection) / 2;  //probably don't need this.
 
lineDirection.SetPosition(1, deflection);

I have no idea why the other versions of this code messed up for you. division screws up because it transforms based on zero as i said earlier in the comments below(when you wanted to transform it based on hitpos). when calculating the length of deflection(magnitude), remember to subtract hitpos or you will get the distance between deflection and zero instead. also on Quaternion’s still hate them.

Here we use the RayCastHit.point if applicable, or the point maxRayLength in that direction if no hit occurs.

This technique should allow you to find the right endpoint for your second LineRenderer.

	var direction: Vector3; //value should be derived from previous collision
	var lineStart: Vector3; //value should be derived from previous collision
	var maxRayLength: float =  5;
	var lineEnd: Vector3; 
	var hit:RaycastHit;
	if(Physics.Raycast(lineStart, direction, hit, maxRayLength)) {
		lineEnd = hit.point;
	}	
	else {
        //assumes direction is of length 1, change to direction.normalized if required.
		lineEnd = lineStart + (direction * maxRayLength); 
	}

    //the following for illustrative purposes only:
	var lr:LineRenderer = gameObject.GetComponent(LineRenderer);
	lr.useWorldSpace = true;
	lr.SetPosition(0,lineStart);
	lr.SetPosition(1,lineEnd);

	Debug.DrawRay(lineStart, lineEnd - lineStart, Color.red, 1.0f);		

Update:

Here is a more complete implementation.
The results illustrated can be achieved by placing this script on a GameObject, and then assigning some with LineRenderers to lr1 and lr2.

var lr2:LineRenderer;
var lr1:LineRenderer;
var direction:Vector3 = new Vector3(1,1,0);
var rayLength : float = 30;
var guideLength:float = 5;

function Update () {
	var initialPosition: Vector3 = transform.position;
	var impactPoint: Vector3;
	var guideEndPoint: Vector3;
	var hit:RaycastHit;
	
	if (!Physics.Raycast(initialPosition, direction, hit, rayLength)) {
		// handle a miss
		Debug.DrawRay(initialPosition, direction.normalized * rayLength, Color.blue, 1.0f, true);	
		lr1.enabled = false;
		lr2.enabled = false;
		return; 
	}

	impactPoint = hit.point;
	guideEndPoint = impactPoint + ( -hit.normal * guideLength );
	
	//draw rays for IDE
	Debug.DrawRay(initialPosition, impactPoint - initialPosition, Color.green, 1.0f, true);	
	Debug.DrawRay(impactPoint, guideEndPoint - impactPoint, Color.red, 1.0f, true);	
	
	//draw lineRenderers for GameScreen
	lr1.enabled = true;
	lr2.enabled = true;
	lr1.SetPosition(0, initialPosition);
	lr1.SetPosition(1, impactPoint);
	lr2.SetPosition(0, impactPoint);
	lr2.SetPosition(1, guideEndPoint);
}

alt text

If you want to draw a line of fixed length from a known starting position and following some fixed direction then you can compute the two end points like this:

// Code snippet

var separation : Vector3 = transform.position - player.transform.position;

var tangent : Vector3 = Vector3.Normalize(separation) * lineLength;

var start : Vector3 = transform.position;
var end : Vector3 = start + tangent;

To give you a little more of a hint, I’ve created a Unity scene and some script code that shows just how to do this. Take a look here for details: the computation of the line you care about is all in the “TargetBall” script/