Search code examples
unity-game-engine2dgame-physics2d-gamesraycasting

Unity - Aim Line (Line Renderer) not showing in 2D shooter


I'm a Unity novice and I'm creating a small 2D shooting game on a school project and I already managed to have a functional shooting system in the main character that even bounces off some objects using Unity Physics.

I now wanted to integrate an aim line that will predict the trajectory of the bullet, including the bounces on objects (bubble-shooter style).

I found a script that uses Raycast and Line Renderer and it supposedly does this and I tried to integrate it into my gun script but although it does not give any error, it simply does not show anything when I test the game. I do not know if the problem is in the settings that I put in the Line Renderer Component or it is in the Script.

Could someone help me understand where my error is and point the right way?

My goal is:

Game idea

My Line Renderer Component Definitions:

Line Renderer Definitions

My Weapon Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(LineRenderer))]
public class Weapon : MonoBehaviour
{
[Range(1, 5)]
[SerializeField] private int _maxIterations = 3;
[SerializeField] private float _maxDistance = 10f;

public int _count;
public LineRenderer _line;

public Transform Firepoint;
public GameObject BulletPrefab;
public GameObject FirePrefab;

void Start()
{
    _line = GetComponent<LineRenderer>();
}

// Update is called once per frame
 void Update()
{
  if (Input.GetButtonDown("Fire1"))
    {
        Shoot();
    }

    _count = 0;
    _line.SetVertexCount(1);
    _line.SetPosition(0, transform.position);
    _line.enabled = RayCast(new Ray(transform.position, transform.forward));
}

void Shoot()
{
    //shooting logic
    var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
    Destroy(destroyBullet, 10f);
    var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
    Destroy(destroyFire, 0.3f);
}

private bool RayCast(Ray ray)
{
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit, _maxDistance) && _count <= _maxIterations - 1)
    {
        _count++;
        var reflectAngle = Vector3.Reflect(ray.direction, hit.normal);
        _line.SetVertexCount(_count + 1);
        _line.SetPosition(_count, hit.point);
        RayCast(new Ray(hit.point, reflectAngle));
        return true;
    }
    _line.SetVertexCount(_count + 2);
    _line.SetPosition(_count + 1, ray.GetPoint(_maxDistance));
    return false;
}
}

Solution

  • Unity has two physics engines one for 2D and one for 3D. The script you provided relies on the 3D physics engine and won't work for 2D colliders. I edited your script to function with 2D colliders.

    Either way make sure that all your game objects use the same physics system. Also the original script only shows the line renderer if it hits something. Best of luck!

    using UnityEngine;
    
    [RequireComponent(typeof(LineRenderer))]
    public class Weapon : MonoBehaviour
    {
        [Range(1, 5)]
        [SerializeField] private int _maxIterations = 3;
    
        [SerializeField] private float _maxDistance = 10f;
    
        public int _count;
        public LineRenderer _line;
    
        public Transform Firepoint;
        public GameObject BulletPrefab;
        public GameObject FirePrefab;
    
        private void Start()
        {
            _line = GetComponent<LineRenderer>();
        }
    
        // Update is called once per frame
        private void Update()
        {
            if (Input.GetButtonDown("Fire1"))
            {
                Shoot();
            }
    
            _count = 0;
            _line.SetVertexCount(1);
            _line.SetPosition(0, transform.position);
            _line.enabled = true;
            RayCast(transform.position, transform.up);
        }
    
        private void Shoot()
        {
            //shooting logic
            var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
            Destroy(destroyBullet, 10f);
            var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
            Destroy(destroyFire, 0.3f);
        }
    
        private bool RayCast(Vector2 position, Vector2 direction)
        {
            RaycastHit2D hit = Physics2D.Raycast(position, direction, _maxDistance);
            if (hit && _count <= _maxIterations - 1)
            {
                _count++;
                var reflectAngle = Vector2.Reflect(direction, hit.normal);
                _line.SetVertexCount(_count + 1);
                _line.SetPosition(_count, hit.point);
                RayCast(hit.point + reflectAngle, reflectAngle);
                return true;
            }
    
            if (hit == false)
            {
                _line.SetVertexCount(_count + 2);
                _line.SetPosition(_count + 1, position + direction * _maxDistance);
            }
            return false;
        }
    }