4
\$\begingroup\$

Here is my missile launcher script, and it is in my opinion borderline acceptable code except for how resource expensive it is. I was wondering if anyone could help me write it better so I could learn a thing or two.

Weapon code:

    [SerializeField]
    private float lockOnTime;
    [SerializeField]
    private GameObject lockOnPrefab;
    [SerializeField]
    private Transform lockOnParent;
    private Dictionary<GameObject, GameObject> targetDict = new Dictionary<GameObject, GameObject>();
    public bool isLockedOn = false;
    public float currentTime;

    private LockOn previousLockOn;
    private int lockOnLayerMask;

    protected override void Start ()
    {
        base.Start();
        lockOnLayerMask = LayerMask.GetMask("LockOnLayer");
        currentTime = lockOnTime;
    }

    protected override void OnDisable()
    {
        base.OnDisable();
        foreach (GameObject go in targetDict.Values)
        {
            Destroy(go);
        }
        targetDict.Clear();     
    }

    protected override void Update()
    {
        base.Update();

        ShowPotentialTargets();
    }

    public override bool Shoot()
    {
        if (isLockedOn && base.Shoot())
        {
            foreach (Transform t in prefabSpawnPoints)
            {
                //GameObject newMissle = (GameObject)Instantiate(instantiatePrefab, t.position, t.rotation);
                //newMissle.GetComponent<Missle>().SetTarget(lockOnTransform);
                currentAmmo -= 1;
            }
            return true;
        }
        return false;
    }

    public override void Aim(bool isPressed)
    {
        base.Aim(isPressed);

        RaycastHit hit;
        bool rayHitSomething = Physics.Raycast(transform.position, transform.forward, out hit, range, lockOnLayerMask);
        if (rayHitSomething && targetDict.ContainsKey(hit.transform.gameObject))
        {
            if (isPressed)
            {
                currentTime -= Time.deltaTime;
                if (currentTime <= 0)
                {
                    isLockedOn = true;
                    currentTime = 0;
                }
            }
            else
            {
                currentTime += Time.deltaTime;
                if (currentTime >= lockOnTime)
                {
                    currentTime = lockOnTime;
                }
                isLockedOn = false;
            }

            LockOn currentLockOn = targetDict[hit.transform.gameObject].GetComponent<LockOn>();
            currentLockOn.isSelected = true;
            currentLockOn.percent = 1 - currentTime / lockOnTime;
            if (hit.transform.tag == "EnemyLockOnCollider")
            {
                currentLockOn.SetUpColor(Color.red);
            }
            else if (hit.transform.tag == "AllyLockOnCollider")
            {
                currentLockOn.SetUpColor(Color.green);
            }
            if (previousLockOn != currentLockOn)
            {
                if (previousLockOn != null)
                {
                    previousLockOn.isSelected = false;
                }
                previousLockOn = currentLockOn;
            }
        }
        else if (previousLockOn != null)
        {
            previousLockOn.isSelected = false;
        }
    }

    public void ShowPotentialTargets()
    {
        foreach (GameObject target in GameObject.FindGameObjectsWithTag("EnemyLockOnCollider"))
        {
            Vector3 screenPoint = Camera.main.WorldToViewportPoint(target.transform.position);
            bool onScreen = screenPoint.z > 0 && screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1;
            if (onScreen && Vector3.Distance(transform.position, target.transform.position) < range)
            {
                if (!targetDict.ContainsKey(target))
                {
                    GameObject targetImage = (GameObject)Instantiate(lockOnPrefab, lockOnParent);
                    LockOn lockOnScript = targetImage.GetComponent<LockOn>();
                    lockOnScript.SetUpTarget(target.transform);
                    targetDict.Add(target, targetImage);
                }
            }
            else
            {
                if (targetDict.ContainsKey(target))
                {
                    Destroy(targetDict[target]);
                    targetDict.Remove(target);
                }
            }
        }
    }

Lock On Code (this goes on the targetet game object):

private Transform target;
public bool isSelected;
public float percent;

[Header("Scale")]
[SerializeField]
private Vector3 startScale;
[SerializeField]
private Vector3 finalScale;

[Header("Color")]
[SerializeField]
private Color defaultColor;
[SerializeField]
private Color startColor;
private Color finalColor;

private RectTransform rect;
private Image image;

void Start()
{
    rect = GetComponent<RectTransform>();

    image = GetComponent<Image>();

    rect.localScale = startScale;       
}

void Update()
{
    transform.position = Camera.main.WorldToScreenPoint(target.position);

    if (isSelected)
    {
        image.color = Color.Lerp(startColor, finalColor, percent);

        rect.localScale = Vector3.Lerp(startScale, finalScale, percent);
    }
    else
    {
        image.color = defaultColor;
    }
}

public void SetUpTarget(Transform target)
{
    this.target = target;
}

public void SetUpColor(Color finalColor)
{
    this.finalColor = finalColor;
}

This code does what i want. It is from a class missle launcher that derives from weapon. When i see the targets on screen they turn white, if a ray hits them that means they are in front of the plane and it starts locking on when i aim with right mouse. When i am fully locked on the target turns red and i am able to shoot at it. My problem is that there is a search for all gameobjects every frame and so many if's. It is really reesource heavy and i dont know how to make it run faster. For example: Caching all targets would be beter for the performance but i dont know when they go off screen and so on... If anyone has time I would really appreciate the help!

\$\endgroup\$
  • 2
    \$\begingroup\$ "This code does what i want" Which is what? There is no problem description in your question. When is this called? Why is this called? \$\endgroup\$ – Mast Nov 4 '17 at 8:45
  • 2
    \$\begingroup\$ Ok edited it my bad. \$\endgroup\$ – Nik Vozelj Nov 4 '17 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.