Search Unity

Projectiles that don't project

Discussion in 'Scripting' started by GeneralShrek, Aug 13, 2019.

  1. GeneralShrek

    GeneralShrek

    Joined:
    Aug 13, 2019
    Posts:
    4
    I apologize if this is a repeat of something that came before; I looked, but couldn't find anything related to this particular issue.
    The portion of the script at issue is supposed to move a launched projectile to the intended target:
    Code (CSharp):
    1. IEnumerator OpenFire(Projectile projectile)
    2. {
    3.     while (GetTargetDistance(targetEnemy) > 0.2f)
    4.         {
    5.         var dir = targetEnemy.transform.localPosition - transform.localPosition;
    6.         var angleDir = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    7.         projectile.transform.rotation = Quaternion.AngleAxis(angleDir, Vector3.forward);
    8.         projectile.transform.localPosition = Vector2.MoveTowards(projectile.transform.localPosition, targetEnemy.transform.localPosition, 5f * Time.deltaTime);
    9.         yield return null;
    10.     }
    11.     if (projectile != null || targetEnemy == null)
    12.     {
    13.         Destroy(projectile);
    14.     }
    15. }
    Everything works getting into the while loop, but the projectiles don't move, and the console error "NullReferenceException: Object reference not set to an instance of an object" links back to the "var dir = targetEnemy....." line. Any thoughts?
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    targetEnemy is probably null. GetTargetDistance probably deals with targetEnemy being null gracefully, but line 5 will generate an error if targetEnemy is null. Add debugging.
     
  3. GeneralShrek

    GeneralShrek

    Joined:
    Aug 13, 2019
    Posts:
    4
    Seems like you're right, but I still can't find the error. My original post had part of the conditional commented out to expose the error; the whole script is as follows:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Tower : MonoBehaviour
    6. {
    7. [SerializeField] private float timeBetweenAttacks;
    8. [SerializeField] private float attackRadius;
    9. [SerializeField] private Projectile projectile;
    10. private Enemy targetEnemy = null;
    11. private float attackCounter;
    12. private bool isAttacking = false;
    13.  
    14. void Update()
    15. {
    16. attackCounter -= Time.deltaTime;
    17. if (targetEnemy == null)
    18. {
    19. Enemy nearestEnemy = GetNearestEnemyInRange();
    20. if (nearestEnemy != null && Vector2.Distance(transform.localPosition, nearestEnemy.transform.localPosition) <= attackRadius)
    21. {
    22. Debug.Log("Enemy in Range!");
    23. targetEnemy = nearestEnemy;
    24. }
    25. }
    26. else
    27. {
    28. if (attackCounter <= 0)
    29. {
    30. Debug.Log("Ready to Fire!");
    31. isAttacking = true;
    32. attackCounter = timeBetweenAttacks;
    33. }
    34. else
    35. {
    36. isAttacking = false;
    37. }
    38. if (Vector2.Distance(transform.localPosition, targetEnemy.transform.localPosition) > attackRadius)
    39. {
    40. targetEnemy = null;
    41. }
    42. }
    43. }
    44.  
    45. void FixedUpdate()
    46. {
    47. if (isAttacking)
    48. {
    49. Debug.Log("Aim!");
    50. Attack();
    51. }
    52. }
    53.  
    54. public void Attack()
    55. {
    56. isAttacking = false;
    57. Projectile newProjectile = Instantiate(projectile) as Projectile;
    58. newProjectile.transform.localPosition = transform.localPosition;
    59. if (targetEnemy = null)
    60. {
    61. Destroy(newProjectile);
    62. }
    63. else
    64. {
    65. Debug.Log("Firing!");
    66. StartCoroutine(OpenFire(newProjectile));
    67. }
    68. }
    69.  
    70. IEnumerator OpenFire(Projectile projectile)
    71. {
    72. while (GetTargetDistance(targetEnemy) > 0.2f && targetEnemy != null && projectile != null)
    73. {
    74. var dir = targetEnemy.transform.localPosition - transform.localPosition;
    75. var angleDir = Mathf.Atan2(dir.y, dir.x) * Mathf.Rag2Deg;
    76. Debug.Log("Target at bearing " + angleDir);
    77. Debug.Log("Distance " + dir);
    78. projectile.transform.rotation = Quaternion.AngleAxis(angleDir, Vector3.forward);
    79. projectile.transform.localPosition = Vector2.MoveTowards(projectile.transform.localPosition, targetEnemy.transform.localPosition, 5f * Time.deltaTime;
    80. yield return null;
    81. }
    82. if (projectile != null || targetEnemy == null)
    83. {
    84. Destroy(projectile)
    85. }
    86. }
    87.  
    88. private float GetTargetDistance(Enemy thisEnemy)
    89. {
    90. if (thisEnemy == null)
    91. {
    92. thisEnemy = GetNearestEnemyInRange();
    93. if (thisEnemy == null)
    94. {
    95. return 0f;
    96. }
    97. }
    98. return Mathf.Abs(Vector2.Distance(transform.localPosition, thisEnemy.transform.localPosition));
    99. }
    100.  
    101. private List<Enemy> GetEnemiesInRange()
    102. {
    103. List<Enemy> enemiesInRange = new List<Enemy>();
    104. foreach(Enemy enemy in GameManager.Instance.EnemyList)
    105. {
    106. if (Vector2.Distance(transform.localPosition, enemy.transform.localPosition) <= attackRadius
    107. {
    108. enemiesInRange.Add(enemy)
    109. }
    110. }
    111. return enemiesInRange;
    112. }
    113.  
    114. private Enemy GetNearestEnemyInRange()
    115. {
    116. Enemy nearestEnemy = null;
    117. float smallestDistance = float.PositiveInfinity;
    118. foreach(Enemy enemy in GetEnemiesInRange())
    119. {
    120. if (Vector2.Distance(transform.localPosition, enemy.transform.localPosition) < smallestDistance)
    121. {
    122. smallestDistance = Vector2.Distance(transform.localPosition, enemy.transform.localPosition);
    123. nearestEnemy = enemy;
    124. }
    125. }
    126. return nearestEnemy;
    127. }
    128. }
    With the added conditions on the while loop, it never gets triggered which lends heavy weight to targetEnemy being null, but I know it's being assigned because I get the debug message "Enemy in Range!". In fact, all the debug messages up to (and including) "Firing!" all trigger properly
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Probably line 59 above. A single "=" is for assignment, so that line makes targetEnemy null instead of checking for null.

    Code (csharp):
    1. if (targetEnemy = null)
     
  5. GeneralShrek

    GeneralShrek

    Joined:
    Aug 13, 2019
    Posts:
    4
    Found the problem! Line 59 sets to null instead of compares to null
     
  6. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Glad you found it :p
     
    SparrowGS likes this.
  7. GeneralShrek

    GeneralShrek

    Joined:
    Aug 13, 2019
    Posts:
    4
    Hey buddy, just wanted to say thank you for all your help. Hopefully one day I can return the favour. Cheers!