Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple expendable Laser script for Unity
using UnityEngine;
using System.Collections;
public class LaserScript : MonoBehaviour
{
[Header("Laser pieces")]
public GameObject laserStart;
public GameObject laserMiddle;
public GameObject laserEnd;
private GameObject start;
private GameObject middle;
private GameObject end;
void Update()
{
// Create the laser start from the prefab
if (start == null)
{
start = Instantiate(laserStart) as GameObject;
start.transform.parent = this.transform;
start.transform.localPosition = Vector2.zero;
}
// Laser middle
if (middle == null)
{
middle = Instantiate(laserMiddle) as GameObject;
middle.transform.parent = this.transform;
middle.transform.localPosition = Vector2.zero;
}
// Define an "infinite" size, not too big but enough to go off screen
float maxLaserSize = 20f;
float currentLaserSize = maxLaserSize;
// Raycast at the right as our sprite has been design for that
Vector2 laserDirection = this.transform.right;
RaycastHit2D hit = Physics2D.Raycast(this.transform.position, laserDirection, maxLaserSize);
if (hit.collider != null)
{
// We touched something!
// -- Get the laser length
currentLaserSize = Vector2.Distance(hit.point, this.transform.position);
// -- Create the end sprite
if (end == null)
{
end = Instantiate(laserEnd) as GameObject;
end.transform.parent = this.transform;
end.transform.localPosition = Vector2.zero;
}
}
else
{
// Nothing hit
// -- No more end
if (end != null) Destroy(end);
}
// Place things
// -- Gather some data
float startSpriteWidth = start.renderer.bounds.size.x;
float endSpriteWidth = 0f;
if (end != null) endSpriteWidth = end.renderer.bounds.size.x;
// -- the middle is after start and, as it has a center pivot, have a size of half the laser (minus start and end)
middle.transform.localScale = new Vector3(currentLaserSize - startSpriteWidth, middle.transform.localScale.y, middle.transform.localScale.z);
middle.transform.localPosition = new Vector2((currentLaserSize/2f), 0f);
// End?
if (end != null)
{
end.transform.localPosition = new Vector2(currentLaserSize, 0f);
}
}
}
@pentlander

This comment has been minimized.

Copy link

@pentlander pentlander commented Apr 26, 2015

Hey thanks a lot for the tutorial. Using your code as a base, I was able to shoot the laser at any angle and I added a fading effect at the end. Here is the code if anyone is interested.

@LegendaryZReborn

This comment has been minimized.

Copy link

@LegendaryZReborn LegendaryZReborn commented May 1, 2016

I've been running into a problem while using this as a template for my beam. In mine, the position of the middle is increased faster than the scaling. Any ideas why?

@shohan4556

This comment has been minimized.

Copy link

@shohan4556 shohan4556 commented Nov 22, 2016

@pentlander : your link is not working

@JoeFinnigan

This comment has been minimized.

Copy link

@JoeFinnigan JoeFinnigan commented Dec 10, 2017

Just wanted to say this has been incredibly helpful with a project I've been working on, and with understanding Raycasting in general. Thank you so much!

@ZoomDomain

This comment has been minimized.

Copy link

@ZoomDomain ZoomDomain commented May 8, 2018

Oh it's a 2D one! that game is cool. http://dmayance.com/unity-expandable-laser/ I'm coding a 3D one and I can do a transparent 2D quad that turns with the camera, except that it will get flat if I look through the end of the lazer.

@GrantK1

This comment has been minimized.

Copy link

@GrantK1 GrantK1 commented Feb 25, 2019

This is very helpful! I have a laser beam i would like to try this out on, but it looks like GameObject.renderer has been depricated in unity 2018.3.6, it has been replaced with GetComponent < Renderer >() (but without the space, part of the comment wouldnt show)Will have to see how i can get this to work, but it would be amazingly helpful if you could add a solution! Thanks for the post.

@BlackCode101

This comment has been minimized.

Copy link

@BlackCode101 BlackCode101 commented May 28, 2020

hi,
I am trying to use your code for vertical laser, but the laser coordinates are not working properly. I have tried to twist the code in many ways but still the sprites are not rendering the way it should. Please review the code if anyone can help i will really appreciate as i am new to the unity.
public class RayCastTest : MonoBehaviour
{
public float floatheight;
public float liftForce;
public float daming;
private Rigidbody2D rb2D;
private float distance;

public GameObject laserStart;
public GameObject laserMiddle;
public GameObject laserEnd;

private GameObject start;
private GameObject middle;
private GameObject end;

// Start is called before the first frame update
private void Start()
{
    rb2D = GetComponent<Rigidbody2D>();
    distance = 0.0f;
}

// Update is called once per frame
private void FixedUpdate()
{
    // Create the laser start from the prefab
    if (start == null)
    {
        start = Instantiate(laserStart) as GameObject;
        start.transform.parent = this.transform;
        start.transform.localPosition = Vector2.zero;
    }

    // Laser middle
    if (middle == null)
    {
        middle = Instantiate(laserMiddle) as GameObject;
        middle.transform.parent = this.transform;
        middle.transform.localPosition = Vector2.zero;
    }


    RaycastHit2D hit = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.down), floatheight);


    float currentLaserSize = floatheight;
     

    if (hit.collider != null)
    {
        hit.transform.GetComponent<SpriteRenderer>().color = Color.red;


        distance = Mathf.Abs(hit.transform.position.y - transform.position.y);
        currentLaserSize = Vector2.Distance(hit.point, this.transform.position);

        float heightError = floatheight - distance;
        float force = liftForce * heightError - rb2D.velocity.y * daming;

        Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.down) * distance, Color.red);

        if (end == null)
        {
            end = Instantiate(laserEnd) as GameObject;
            end.transform.parent = this.transform;
            end.transform.localPosition = Vector2.zero;
        }
        //rb2D.AddForce(Vector3.down * force);
    }
    else
    {
        // Nothing hit
        // -- No more end
        if (end != null)
        {
            Destroy(end);
        }
        Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.down) * floatheight, Color.red);
    }

    float startSpriteWidth = start.GetComponent<Renderer>().bounds.size.y;
    if (end != null)
    {
        endSpriteWidth = end.GetComponent<Renderer>().bounds.size.y; //end.renderer.bounds.size.x;
    }

    middle.transform.localScale = new Vector3(currentLaserSize, middle.transform.localScale.y, middle.transform.localScale.z);
    middle.transform.localPosition = new Vector2(0f, -(currentLaserSize / 2f)); 

    if (end != null)
    {
        end.transform.localPosition = new Vector2(0f, currentLaserSize);
    }

I think the main problem is in these two lines:

middle.transform.localScale = new Vector3(currentLaserSize, middle.transform.localScale.y, middle.transform.localScale.z);
middle.transform.localPosition = new Vector2(0f, -(currentLaserSize / 2f));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.