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!