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
0
Question by RyanZimmerman87 · Oct 22, 2013 at 10:30 PM · line rendererlaser beamelementsy height

Need help setting correct Y height for laser beam with 50 elements

K so I have a laser set up in my game which is using a Line Renderer which shoots up to 50 individual particles or "Elements" to create the visual laser effect. This allows the laser to kind of pulsate due to a "noise" variable causing the x and z positions to change positions slightly along the path.

Everything is working well except one thing. I'm not sure how to go about setting the Y height properly since each of the 50 elements need to have a custom y height. Currently the ray just keeps the same y-height as how it starts which works fine for some enemies but shoots over the head of others so I have to make the enemy colliders taller and it just looks unnatural when the laser isn't hitting their body.

I've tried some solutions but have been unable to get it work correctly so far. This kind of math is not my strong point and with the individual element system I'm not sure if it's even possible with my current system but I was hoping someone might have some answers and advice for me.

Example of the laser code which sets the offset positions (x, y, z) for each of the 50 elements. Not all 50 elements will be used if the laser hits a target before it's max range.

      void RenderLaser()
         {
         
         //length = 50
         for(int i = 0; i<length; i++)
         {
         //offset is a vector position for each of the 50 elements
         //player will be facing the target with other controls
         
         offSet.x = myTransform.position.x + i*myTransform.forward.x + Random.Range(-noise,noise);
         
         offSet.z = i*myTransform.forward.z + Random.Range(-noise,noise) + myTransform.position.z; 
         
         //here is the problem I need to set the Y height correctly
         //currently using
         offSet.y = myTransform.position.y;
         
         position[i] = offSet;
         
         lineRenderer.SetPosition(i, position[i]);
         }

So I have access to the gameObject that the laser is hitting, so I would think that I should be able to somehow set the y positions correctly based on what % of distance they are from the player to the enemy?

Right now I had it set up so RenderLaser() is called every Update() perhaps fixedUpdate() would be better for these calculations, not sure if it should matter it is a visual effect so Update should work?

I've tried a bunch of stuff trying to set the y height based on the start of laser position from the player and the enemy transform position, but like I said math is not my strong point and the unique elements are kinda throwing me off.

Examples of how I've tried to set y height:

 //the laser destination position
 laserTargetVector = damageHit.collider.gameObject.transform.position;
 
 //distance from laser start to finish
 float distanceToEnemy = Vector3.Distance (myTransform.position, laserTargetVector);
 
 //attempt to get the y height change to calculate slope
 float newOffSetYCalculation = myTransform.position.y - laserTargetVector.y;
 
 //I would think I should be able to solve with just the 3 pieces of info above but I'm not quite getting it seems like
 
 
 //Here's another example of something I've tried I think this is the closest solution I've had 
 //but there's so many comments from all the things I've tried
 //things getting really messy to keep track of
 
 
 float slopeRatio = (myTransform.position.y - laserTargetVector.y)/(myTransform.position.x - laserTargetVector.x); 
 
 offSet.y = myTransform.position.y - (slopeRatio*i);
 

I think those are some decent examples of what I'm trying to do. I just feel like I'm a bit out of my league mathematically here. It seems like I should be able to use the slope ratio in relation to my offset.y position to do this. The trouble seems to be that I'm not sure how to determine the y position for each of the 50 elements accurately. I need to determine the % of distance each y particle is from the player to enemy to determine height.

I'm not sure if this is possible with the element system since I'm not sure if they are always spaced out consistent distances since this is called from Update, and since it's not always 50 elements if the laser doesn't go the full length it makes things even more complicated.

I'm thinking maybe I need to get the distance of every y particle before setting the height, so set the x and z position first then get that position to calculate y height?

I dunno this is very complicated for me hopefully someone can help!

Essentially I just want the unique particles to follow the exact path a normal line renderer would be from the player's hand to the enemies body. I know how to do this but not with the 50 element line renderer thing I'm trying to work with.

Comment
Add comment
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

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by mattmanj17 · Oct 23, 2013 at 01:22 AM

You could calculate the positions like this.

1.Calculate the "ideal" line between the source of the lazer and its target (target.position-transform.position).

2.For the " i'th " point in the line, assign it the position i*(ideal/50). At this point the line renderer is just a straight line from the source to the target.

3.Add a random "noise" vector to each point.

An example script using this method below:

 using UnityEngine;
 using System.Collections;
 
 public class laserScript : MonoBehaviour {
     public Transform target;
     public float noise =5f;
     private LineRenderer laser;
     void Awake(){
         laser=GetComponent<LineRenderer>();
     }
     void Update(){
         render_line();
     }
     void render_line(){
         for(int i=0;i<50;i++){
             laser.SetPosition(i,calculateIthPosition(i));
         }
     }
     Vector3 calculateIthPosition(int i){
         Vector3 ideal=(target.position-transform.position);
         Vector3 ithIdeal = i*(ideal/50);
         return transform.position+(ithIdeal+noiseVector()); 
         //I was getting some weird results with just "ithIdeal+noiseVector()", 
         //but i think that was because I had 
         //"use world space" on in the line renderer
     }
     Vector3 noiseVector(){
         return (Random.onUnitSphere*noise);
     }
 }

and here is a picture of the code working

alt text

is this the sort of effect you were going for?

P.S. Your idea is very clever. I would have never thought to use a line renderer like that.


laser example.jpg (16.8 kB)
Comment
Add comment · Show 2 · 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 RyanZimmerman87 · Oct 23, 2013 at 11:14 PM 0
Share

Thank you so much for this solution that seems to make a lot of sense and nice example! Looks like you already got it working!

I wish I could take credit for idea to use the line renderer like this, I agree it's a really cool application! I got the idea though from a poster on these forums, if I remember correctly he was basically just posting a really nice laser script example and said people were free to use it in their own projects!

I just found the post gotta give credit where it's due:

http://forum.unity3d.com/threads/122500-Laser-Beam-Script-in-C

avatar image RyanZimmerman87 · Oct 24, 2013 at 11:31 PM 0
Share

$$anonymous$$ I was able to implement this solution with just some $$anonymous$$or tweaks for my system!

$$anonymous$$ost importantly I had to replace:

Vector3 ithIdeal = i*(ideal/50);

with:

Vector3 ithIdeal = i*(ideal/length);

And I think since your guys answers were so good I'll include some more of the code that helps get the length, I didn't realize it was so important to the solution probably should have included that in my first post.

So in the function RenderLaser() there is an immediate function call that deter$$anonymous$$es the length.

 maxLengthReal = 51;

 void RenderLaser()
 {
 UpdateLength();
 
 //remaining RenderLaser() code
 )
 
 //this code is a little excessive and seems to work even if I remove certain lines...
 //might be useful to others though and is required for my system to work
 
 void UpdateLength()
 {
         
 RaycastHit[] hit;
         
 hit = Physics.RaycastAll(startLaserCollisionTransform.position, startLaserCollisionTransform.forward, maxLengthReal, ignoreLaserBeam$$anonymous$$ask & enemyRigidBody$$anonymous$$ask & ignorePlayer$$anonymous$$ask);
         
 int i = 0;
         
 while(i < hit.Length)
 {
 //***  SEE$$anonymous$$S TO WOR$$anonymous$$ FINE WITHOUT THIS LIN$$anonymous$$..
 length = (int)$$anonymous$$athf.Round(hit[i].distance) +2;
                 
 position = new Vector3[length];
                 
 lineRenderer.SetVertexCount(length);
 
 //***  SEE$$anonymous$$S TO WOR$$anonymous$$ FINE WITHOUT THIS LIN$$anonymous$$..
 lineRenderer.SetPosition(1, new Vector3(0,0, 100));
 
 i++;
             
 // this return makes laser not go through multiple objects
 return;
 }
         
 if (Player$$anonymous$$oveScript.playerLaserBeamBool == true)
 {
 length = (int)maxLength;
 
 position = new Vector3[length];
             
 lineRenderer.SetVertexCount(length);
 }
         
 }

I also added one bool condition to deter$$anonymous$$e whether to call the function:

lineRenderer.SetPosition(i,calculateIthPosition(i));

Based on what the laser hits it either calls that function or executes the code I had before to shoot straight.

The system appears to be working perfectly now! So happy thanks for all the help guys!

avatar image
0

Answer by robertbu · Oct 23, 2013 at 01:31 AM

I have to agree with @mattmanj17. Your idea is clever. Here is my take at a solution. Before you attempt to integrate it into your app, test it in a clean scene to make sure it is what you are going for:

  • Create a game object near the camera for your fire point.

  • Add a LineRenderer component to the game object. Set the material and width as appropriate.

  • Add this script.

  • Put an object in the scene to act as a target.

  • Initialize the 'target' of the script in the inspector by dragging and dropping the target game object from hierarchy onto the 'target' variable.

  • Hit play. Move the target around in the inspector.

      using UnityEngine;
         using System.Collections;
         
         public class Laser : MonoBehaviour {
             public int length = 50;
             public float noise = 0.1f;
             public Transform target;
             
             private LineRenderer lineRenderer;
             
             void Start () {
                 lineRenderer = GetComponent<LineRenderer>();
                 lineRenderer.SetVertexCount (length+1);
             }
             
             void Update() {
                 RenderLaser(transform.position, target.position);    
             }
             
             void RenderLaser(Vector3 startPos, Vector3 endPos) {
                  Vector3 targetVector = endPos - startPos;
                 float lineLength = targetVector.magnitude;
                 targetVector = targetVector.normalized * lineLength / length;
                 Vector3 ortho = Vector3.Cross (targetVector, Vector3.up).normalized;
                 Vector3 ongoing = startPos;
                 
                 lineRenderer.SetPosition(0, startPos);
                 
                 for(int i = 1; i <= length; i++) {
                        ongoing += targetVector;    
                     Vector3 offset = Quaternion.AngleAxis(Random.Range(0.0f, 360.0f), targetVector) * (ortho * Random.Range (0.0f, noise));
                     lineRenderer.SetPosition(i, ongoing + offset);
                 }
             }
         }
    
Comment
Add comment · Show 1 · 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 RyanZimmerman87 · Oct 23, 2013 at 11:18 PM 0
Share

Thanks! That sounds like an excellent way to debug this to make sure everything is working in all scenarios!

I'll let you guys know if I get this working in near future, going to try this very soon!

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

15 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

Related Questions

Bouncing Laser Beam 1 Answer

Perspective top down laser. 1 Answer

How to block a LineRenderer with a shield from a moving origin point 0 Answers

why can't Line Renderer catch movement of camera? 0 Answers

how to know when list is empty? 3 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