Star Trek Blue Phaser Beams

Hello!

I have made some Star Trek phaser beams for my ship, the shoting part works as it should do.

The beams starting point is set to the 6 lower beam banks on the ship, when you press spacebar you see the blue phaser from the exact point you have sett them to start from.

However… if you move the ship while you shooting, the beams do not follow the beam points where they are set to, they just stays at the position where they first was beamed and pointing at the enemy target.
Its like you leave the beam lines there while you moving away from them.

I made it work this way
1: i have the “PlayerShooting” script on the space ship with the phaser prefab draged to the script.
2: a phaser prefab in the project (not in the scene) thats is set to selfdestruct, a line renderer and the projectile script.

Please help me “Lock” the beams at the BeamPoints.

PlayerShooting and BeamProjectile script

using UnityEngine;
using System.Collections;

public class BeamProjectile : 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);   
    }

    public 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);
        }
    }
}
using UnityEngine;
using System.Collections;

public class PlayerShooting : MonoBehaviour {

    public float coolDown = 0f;
    public float fireRate = 0f;

    //Checks to se if We actually firing
    public bool isFiring = false;

    //firing point transform for launching beams
    public Transform lowerLeftBeamPoint;
    public Transform lowerLeftRBeamPoint;
    public Transform lowerRightBeamPoint;
    public Transform lowerRightRBeamPoint;
    public Transform lowerCenterBeamPoint;
    public Transform lowerCenterRBeamPoint;

    public Transform upperLeftBeamPoint;
    public Transform upperRightBeamPoint;
    public Transform upperCenterBeamPoint;

    //Beam object
    public GameObject beamPrefab;

    public AudioSource beamFXSound;



    void Start () {
        isFiring = false;
  
    }
  
    // Update is called once per frame
    void Update () {

        CheckInput ();
        coolDown -= Time.deltaTime;

        if(isFiring == true)
        {
            // the player has shooting the beam!
            Fire();
        }
  
    }

    void CheckInput()
    {
        if(Input.GetKeyDown("space"))
        {
            isFiring = true;
        }
        else
        {
            isFiring = false;
        }
    }

    void Fire()
    {
        if (coolDown > 0)
        {
            return; //Dont fire
        }
        // Play the sound effect when player is firing
        if (beamFXSound != null)
        {
            beamFXSound.Play ();
        }
        GameObject.Instantiate (beamPrefab, lowerCenterBeamPoint.position, lowerCenterBeamPoint.rotation);
        GameObject.Instantiate (beamPrefab, lowerRightBeamPoint.position, lowerRightBeamPoint.rotation);
        GameObject.Instantiate (beamPrefab, lowerLeftBeamPoint.position, lowerLeftBeamPoint.rotation);
        GameObject.Instantiate (beamPrefab, lowerCenterRBeamPoint.position, lowerCenterBeamPoint.rotation);
        GameObject.Instantiate (beamPrefab, lowerRightRBeamPoint.position, lowerRightBeamPoint.rotation);
        GameObject.Instantiate (beamPrefab, lowerLeftRBeamPoint.position, lowerLeftBeamPoint.rotation);

        coolDown = fireRate;
    }
}

I think we might need more information how do your beams work? Are they instant or do they travel at a certain distance?

If I recall Star Trek correctly, their laser beams are instant. But I guess you want your beams to:

  1. Follow your projectile as they are traveling to your opponent.
  2. Follow your cannon from where they were shot.
using UnityEngine;
using System.Collections;
public class BeamProjectile2 : MonoBehaviour
{
    public Transform       source;              // that should be your cannon I guess?
    public LineRenderer  lineRenderer;    //assume this exists

    public float speed = 2f; // speed of beams traveling world space
    public int damage = 25; // damage to other objects that beams deals

    private Transform thisTransform;  // chached transform for this beam
    public Transform beamHitFXPrefab;
    // Use this for initialization
    void Start ()
    {
        thisTransform = transform;
 
    }
 
    // Update is called once per frame
    public void Update ()
    {
        thisTransform.position += Time.deltaTime * speed * thisTransform.forward;

        lineRenderer.SetPosition(0, source.position);
        lineRenderer.SetPosition(1, thisTransform.position);
    }
}

As your projectile is going in a direction, just render a line between current position and the source. Be sure to link via inspector everything :slight_smile:

Thanks for your reply!
Iant line renderer instant as deafault? I dont thinkt the name “projectile” do the name right since it just a line renderer and no projectile thats beeing shot…just a line renderer.

Yes you are correct, i want the beams to follow the cannon/beam banks while it also follows the target, and i cant just figure out how to do that :slight_smile:

If you want instant laser beams, you can then do this:

using UnityEngine;
using System.Collections;
public class BeamProjectile2 : MonoBehaviour
{
    public Transform       source;              // that should be your cannon I guess?
    public Transform       target;
    public LineRenderer  lineRenderer;    //set this in inspector
   
    public float range = 100f;
    public int damage = 25; // damage to other objects that beams deals

    public Transform beamHitFXPrefab;

    // Use this for initialization
    void Start ()
    {
        
    }

    // Update is called once per frame
    void Update ()
    {
        if (target == null)
        {
             lineRenderer.enabled = false;
             return;
        }

        lineRenderer.enabled = IsWithinRange();

        if ( !IsWithinRange() )
             return;

        lineRenderer.SetPosition(0, source.position);
        lineRenderer.SetPosition(1, target.position);

        // insert your damage code here
        target.SendMessage("DoDamage", SendMessageOptions.RequireReceiver);
    }

    bool IsWithinRange()
    {
        return Vector3.Distance(source.position, target.position) < range;
    }
}

Although this is bare bones, you have to supply remaining logic. Don’t forget to set up your LineRenderer properties in inspector.

I got a error when i tried this bare bone code, so i might have done some wrong.

I added that code on my existing phaser prefab that contain a line renderer as i did with my other posted code, made a sound prefab and added it to the script, added the target + 1 already made source point (cannon) on the ship as the script want it

The error i getting is this, i think it is about the target?

LineRenderer.SetPosition index out of bounds!
UnityEngine.LineRenderer:SetPosition(Int32, Vector3)
BeamProjectile2:Update() (at Assets/Space Graphics Toolkit/ScriptsCustom/BeamProjectile2.cs:35)

Just to confirm, you set Positions size to 2 in inspector?

1 Like

Yes that was the problem, how ever, there is no visible beams :open_mouth:
I can see the clones being made, but thats all.

EDIT: just to say, the phaser prefab contains the line renderer, and it seams to be ok in the inspector where you assign it.

EDIT2: if i made the distance higher i saw the beams, but they seams to beam from the centre of the scene and not from where the cannon source are

In order to get line renderer working, you have to set up the material and colors as well.

In the materials, click and drag a material that will be used for your lasers.
Positions have to be set to size 2 for this case.
Width atleast 1.
Also assign colors.
Don’t forget to select world space.

I hope this helps!

Yes all that is set correctly, except from the beams thats fixed to fit the size of the phaser cannons, but the beams comes from the centre of the scene of some reason, even if i have the beams set to 1 (big as hell lol)

Lol, I guess centre of the scene is position 0,0,0 right? Could you set starting color to be red and ending color blue, so we can determine is it source or target placed at centre of scene >_>

Its the source, you see the sun? tjats the centre of the scene

That is strange, I just noticed your values in line renderer are not updated in play mode. Using:

 lineRenderer.SetPosition(0, source.position);
lineRenderer.SetPosition(1, target.position);

should update values in inspector accordingly. Could you post how your script looks like now?

I have not done enuthing but removed the damage message for now.
but shouldnt this

lineRenderer.SetPosition(0, source.position);

be something like this?

lineRenderer.GetPosition(0, source.position);

Heres the full code as it is

using UnityEngine;
using System.Collections;
public class BeamProjectile2 : MonoBehaviour
{
    public Transform       source;        // that should be your cannon I guess?
    public Transform       target;
    public LineRenderer  lineRenderer;    //set this in inspector
  
    public float range = 100f;
    public int damage = 25; // damage to other objects that beams deals
  
    public Transform beamHitFXPrefab;
  
    // Use this for initialization
    void Start ()
    {
      
    }
  
    // Update is called once per frame
    void Update ()
    {
        if (target == null)
        {
            lineRenderer.enabled = false;
            return;
        }
      
        lineRenderer.enabled = IsWithinRange();
      
        if ( !IsWithinRange() )
            return;
      
        lineRenderer.SetPosition(0, source.position);
        lineRenderer.SetPosition(1, target.position);
      
        // insert your damage code here

    }
  
    bool IsWithinRange()
    {
        return Vector3.Distance(source.position, target.position) < range;
    }
}

I’m sorry, but I guess I can’t really help much further. Script seems fine since I’m using something similar and it works. When I was working with LineRenderer this tutorial helped me out:

I hope you manage to solve this out. Best of luck!

Although, as a last idea, you could perhaps remove:

lineRenderer.enabled = IsWithinRange();
   
if ( !IsWithinRange() )
     return;

Maybe it never reaches SetPosition since it is not within range?

Nope that didnt help, maybe i have done some wrong somewhere, i have no clue lol. But thatks for your time!
I will watch that tube in a moment.

Thanks again!