Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

I changed my enemies and bullets into prefabs, and now I can't get collisions to work.

Discussion in 'Editor & General Support' started by AbelM03, Apr 25, 2020.

  1. AbelM03

    AbelM03

    Joined:
    Aug 26, 2018
    Posts:
    21
    So I'm working on a very basic top-down shooting game prototype, but with a gimmick that makes it so there's red and blue enemies, and you have two projectiles you can fire: red projectiles on left click, and blue projectiles on right click. The red projectiles kill the blue enemies, and the blue projectiles kill the red enemies. If you hit an enemy with the wrong color projectile, for example, hitting a blue enemy with a blue projectile, you'll take a damage from it. The enemies also move towards you, and will deal damage to you whenever they collide with you. Enemies also randomly spawn around you.

    A bit ago I was at a point where the player could fire both red and blue projectiles (they don't do anything except get destroyed on impact yet though), and the player could take damage from enemies and lose the game. However, when I attempted to implement the enemy spawner, destroying enemies with the projectiles, and adding to the player's score, the game simply broke. I believe it has to do with the fact that both my bullets and my enemies are both prefabs now, which is causing a lot of issues with collisions.

    Here's the EnemyAI script, which is where most of the errors seem to be coming from. The error I keep getting is "NullReferenceException: Object reference not set to an instance of an object
    EnemyAI.OnCollisionEnter2D (UnityEngine.Collision2D target) (at Assets/Scripts/EnemyAI.cs:27)"

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class EnemyAI : MonoBehaviour
    6. {
    7.  
    8.     public float enemySpeed;
    9.  
    10.     public Transform target;
    11.  
    12.     public GameStats stats;
    13.  
    14.  
    15.     void Start()
    16.     {
    17.         target = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();
    18.     }
    19.  
    20.     void Update()
    21.     {
    22.         transform.position = Vector2.MoveTowards(transform.position, target.position, enemySpeed * Time.deltaTime);
    23.     }
    24.  
    25.     void OnCollisionEnter2D(Collision2D target)
    26.     {
    27.         stats.playerHealth = stats.playerHealth - 10;
    28.     }
    29. }
    30.  
    Here's the enemy spawner script as well, since I started getting errors in the AI script after I implemented it:

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5. public class EnemySpawner : MonoBehaviour
    6. {
    7.     [SerializeField]
    8.     private float spawnRadius = 7, time = 1.5f;
    9.     public GameObject[] enemies;
    10.     void Start()
    11.     {
    12.         StartCoroutine(SpawnAnEnemy());
    13.     }
    14.     IEnumerator SpawnAnEnemy()
    15.     {
    16.         Vector2 spawnPosition = GameObject.FindGameObjectWithTag("Player").transform.position;
    17.         spawnPosition += Random.insideUnitCircle.normalized * spawnRadius;
    18.         Instantiate(enemies[Random.Range(0, enemies.Length)], spawnPosition, Quaternion.identity);
    19.         yield return new WaitForSeconds(time);
    20.         StartCoroutine(SpawnAnEnemy());
    21.     }
    22. }
    23.  
    Any help would be highly appreciated, since I'm honestly incredibly confused at the moment.

    If you need scripts for anything else to help solve the problem, just let me know.
     
  2. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    Null reference exception means that the object you are trying to access in your code is not available. So, have you assigned an object that is required? I don't have time to go though your code, but when you use find to get your objects (Like your targeted player in your first script), debug your code (just print out the object) after you've tried to assign it using find, and see if you actually got an object or if it's a null.

    And if the errors began after you did changes, maybe you forgot to set something correctly, like the tag you are using to find the player?

    And it's not really a good idea to use that Find everywhere, especially for things that are somewhat permanent like the player. You should cache it or use it from a static reference that you've assigned once.
     
  3. AbelM03

    AbelM03

    Joined:
    Aug 26, 2018
    Posts:
    21
    I think the issue may be that now that the objects are prefabs, they for whatever reason cannot find the GameManager object, which is where my script that handles score and player health is attached to. I can't seem to figure out how to fix this, though.
     
  4. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    Well, where do you try to find your GameManager, I didn't see that in your code.

    But just do a debug print where you're trying to access it, to see what you got, and I'm pretty sure you will get a null.
     
  5. AbelM03

    AbelM03

    Joined:
    Aug 26, 2018
    Posts:
    21
    I'm trying to modify the GameStats script where the player health and score are stored, and the GameStats script is located in the GameManager object. How would I access that script in the game manager from the EnemyAI script?
     
  6. Olmi

    Olmi

    Joined:
    Nov 29, 2012
    Posts:
    1,553
    Just get the script in your object. This is not the best way of doing things but something like this:
    (You should cache these or access them via static variable or use dependency injection (i.e. just feed the knowledge of that object to another object when you initialize it.))

    Code (CSharp):
    1. GameStats gameStats;
    2.  
    3. void Start()
    4. {
    5.     gameStats = GameObject.Find("GameManager").GetComponent<GameStats>();
    6. }
    This would get the class instance of type GameStats in a scene object called GameManager.

    So you just first find the object, then that GetComponent tries to get a component/class instance you specify in those angle brackets.
     
    Last edited: Apr 25, 2020