Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by oliver-jones · Dec 06, 2013 at 05:12 PM · raycastlinerenderermaths

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

Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image meat5000 ♦ · Dec 07, 2013 at 12:02 PM 0
Share

Isn't it the example in the docs? I've only had a glance but it seems like you need to lay down multiple sections of unit length line to the size you want.

avatar image oliver-jones · Dec 07, 2013 at 12:15 PM 0
Share

Unfortunately the info within the docs isnt what I am looking for, it doesn't show me how to shorten the line - my problem is more of a mathematical issue I guess, rather than the functionality behind the line renderer itself. Thanks anyway

avatar image meat5000 ♦ · Dec 07, 2013 at 12:29 PM 0
Share

I'm not so sure. The docs set line length by simply adding in more vertex points, I believe. Otherwise the 'sine wave curve' would be some spirograph mess :)

I'm assu$$anonymous$$g the LineRenderer simply draw from a point to the next assigned vertex. If you want to make it shorter, assign a new vertex.

Of course, I could be wrong... I've never used the LineRenderer, I'm just looking at the example.

avatar image MrVerdoux · Dec 10, 2013 at 04:29 PM 0
Share

Will it only have two points? If that is the case, isn´t it enough to normalize like this

 deflection = 5*deflection.normalized;

Or did I misunderstood your question?

avatar image Fornoreason1000 · Dec 11, 2013 at 10:31 AM 1
Share

@$$anonymous$$rVerdoux that won't work, since the direction is changed there(it may not seem like it but it does).

deflection is a displacement from hitpos(well its a reflection but its based of hitpos), if you were to to do a distance check you will find it is 5 meters from zero not hitpos. he needs this

 deflection = (deflection -hitPos).normalized * 5 + hitPos;

I went over this in my edited answer, basically this code removes the displacement, normalizes, then displaces it again in order to maintain its direction. with out the displacement being taken to account, the direction will rotate to zero giving weird results.

in other words when you look at a Vector , your look direction is the difference between you and the vector you are trying to look at, makes sense? but the code you use assumes a zero displacement, so if your position was zero and only zero, your code will work(since the difference between an object an zero is always that object).

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Fornoreason1000 · Dec 07, 2013 at 12:40 PM

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 : http://quiz.uprm.edu/visual3d/manual/coor_sys/slope_line.html

http://en.wikipedia.org/wiki/Quaternion (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.

Comment
Add comment · Show 13 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image oliver-jones · Dec 07, 2013 at 06:05 PM 0
Share

Isnt this over complicating things? I only want to cap the max line renderer. Right now, the line goes on for a distance of 30. I want to change it to 5, but if I do that, it messes up the coordinates (unless I reduce the raycast length from 30, to 5 too - but then the raycast is restricted to 5, which I don't want)

avatar image Fornoreason1000 · Dec 07, 2013 at 07:32 PM 0
Share

wait what really? you could normalize it then multiply it by 5. based on that its simple vector math. http://docs.unity3d.com/Documentation/ScriptReference/Vector3-normalized.html

using a piece of paper, i did this.

  1. first subtract ball pos from hitpos, this will give us the direction between the two.

  2. normalize that and multiply by 5,

  3. add the ball vector so it return to normal. the result is your line renderer capped vector.

Hint: do this after you raycast

avatar image oliver-jones · Dec 07, 2013 at 08:00 PM 0
Share

Okay, this sounds good - let me have a play with my code, and I'll get back to you

avatar image oliver-jones · Dec 07, 2013 at 08:03 PM 0
Share

Wait, where are you getting ball pos from? Remember, I want to cast this line from my Second ball, which is the 'hitPos', and direct it in 'newDirection * rayLength'.

avatar image oliver-jones · Dec 07, 2013 at 08:05 PM 0
Share

The second line cast doesn't have an end position, it's just getting the first line cast, and reflecting it really.

Show more comments
avatar image
0

Answer by KellyThomas · Dec 07, 2013 at 03:22 PM

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

Comment
Add comment · Show 7 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image oliver-jones · Dec 07, 2013 at 05:21 PM 0
Share

This isnt capping the max length of my line renderer, only the raycast - I dont want to restrict the raycast itself, just the line renderer of a maximum of 5

avatar image KellyThomas · Dec 07, 2013 at 05:42 PM 0
Share

lineEnd = lineStart + (direction * lineLength); will find your endpoint if:

  • lineStart is the starting point

  • direction is a unit vector defining direction

  • lineLength is the length you want the line to have.

Once you have the start and end points just plug them into the LineRenderer.

avatar image oliver-jones · Dec 07, 2013 at 05:48 PM 0
Share

I already have the location of my line end: 'newDirection * rayLength' - I just want to cap it at a certain length - none of these answers are working and I'm getting really confused by the whole situation here :/

avatar image KellyThomas · Dec 07, 2013 at 05:49 PM 0
Share

Ins$$anonymous$$d of rayLength use the capLength.

avatar image oliver-jones · Dec 07, 2013 at 05:54 PM 0
Share

Where are you getting capLength from? If I change the rayLength in 'newDirection * rayLength' from something different from the raycast length (which is 30 right now), it goes all messed up, plus the line still changed length... I want it to always be a length of 5.

Show more comments
avatar image
0

Answer by Draitch · Dec 07, 2013 at 04:46 PM

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/

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

21 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

LineRenderer (Laser Beam) is not following the ray it's going on the wrong direction when reflecting 1 Answer

Help with LineRenderer 1 Answer

Making a lineRenderer end 10 units in front of a gameObject. 1 Answer

Setting the position of linerenderer 1 Answer

Laser LineRenderer Tapers after first Reflect 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges