Enemies and Friendlies shooting at each other but nobody disappears

I’ve triple checked my rigidbodies for enemy and player and they are ticked kinematic. Colliders are ticked as triggers.

Enemy Script is attached below. Any advice is welcome.

Thanks

William

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

public class EnemyBehavior : MonoBehaviour {
	public GameObject projectile;
	public float beamSpeed = 10.0f;
	public float health = 150f;
	public float shotsPerSeconds = 0.5f;
	private Controller controller;

	void Update ()
	{
		float probability = Time.deltaTime * shotsPerSeconds;
		if (Random.value < probability) {
			Fire ();	
		}
	}
		void Fire ()
		{ 
		Vector3 startPosition = transform.position + new Vector3 (0, -1, 0);
		GameObject missile = Instantiate (projectile, startPosition, Quaternion.identity); 
		missile.GetComponent<Rigidbody2D>().velocity = new Vector2 (0, -beamSpeed);
		}
		
	void OnTriggerEnter2D(Collider2D coll)
		{
		 Projectile missile = GetComponent<Collider>().gameObject.GetComponent<Projectile>();  
		if (missile) 
		{
			health -= missile.GetDamage(); 			 
			missile.Hit(); 
			if (health <= 0) 
			{ 
				Destroy (gameObject);
			}else 
			{
				Debug.Log("Shot was null");	
			}
		}
	}
}

Hi,

In your OnTriggerEnter2D method, add the following line right at the beginning;

Debug.Log("Method OnTriggerEnter2D has been triggered.");

Run the game again, does this message appear in the console when your projectiles collide with the player/enemies?

Also, this line;

Projectile missile = GetComponent<Collider>().gameObject.GetComponent<Projectile>(); 

should be this;

Projectile missile = coll.gameObject.GetComponent<Projectile>(); 

This references coll the collision data which is passed into the OnTriggerEnter2D method, if I had to guess, your existing line of code probably returns null and as such missile is null and the rest of the code in the if statement doesn’t execute.

The above Debug statement will help you to see if initially you are actually even making it to this method, if not, then you can start to check the Inspector for other issues. If you are, then the issue is in the code, most likely this line above.

Hope this helps :slight_smile:


See also;

Projectile missile = GetComponent<Collider>().gameObject.GetComponent<Projectile>();

If I’m reading that correctly it checks the current gameobject for it’s collider and then goes to the gameobject itself then tries to find the projectile class but this is all happening on the enemy game object not the object doing the triggering so the if statement is returning false.

Try changing it to

Projectile missile = coll.GetComponent<Projectile>();

Your code defines the object doing the triggering as coll so this returns the projectile class from the triggering object.

Rob,

Thanks for your help but I think I have made a mess of things. I now have no beams launching from the Player and the beams launched from the Enemy are not moving. I’m attaching my Controller script and my EnemyBehavior scripts. It is all a mystery to me!

Thanks in advance.

William

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class EnemyBehavior : MonoBehaviour {

    public GameObject projectile;

    public float projectileSpeed = 10.0f;

    public float health = 150f;

    public float shotsPerSeconds = 0.5f;

    private Controller controller;

    void Update ()

    {

        float probability = Time.deltaTime * shotsPerSeconds;

        if (Random.value < probability) {

            Fire ();    

        }

    }

        void Fire ()

        { 

        Vector3 startPosition = transform.position + new Vector3 (0, -1, 0);

        GameObject missile = Instantiate (projectile, startPosition, Quaternion.identity); 

        missile.GetComponent<Rigidbody2D>().velocity = new Vector2 (0, -projectileSpeed);

        }

        

    void OnTriggerEnter2D(Collider2D coll)

        {

        Projectile missile = coll.gameObject.GetComponent<Projectile>();  

        if (missile) 

        {

            health -= missile.GetDamage();              

            missile.Hit(); 

            if (health <= 0) 

            { 

                Destroy (gameObject);

            }else 

            {

                Debug.Log("Shot was null");    

            }

        }

    }

} 
using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Controller : MonoBehaviour {

        public GameObject projectile;

        public float projectileSpeed = 10f;

        public float firingRate = 0.2f;        

        public float speed = 15.0f;

        public float padding = 1f;

        public float health = 150f;

        private float xmax;

        private float xmin;

        

        

        

        void Start(){

            

            float distance = transform.position.z - Camera.main.transform.position.z;

            Vector3 leftmost = Camera.main.ViewportToWorldPoint (new Vector3 (0, 0, distance)); 

            Vector3 rightmost = Camera.main.ViewportToWorldPoint(new Vector3(1,0,distance));

            xmin = leftmost.x + padding;

            xmax = rightmost.x - padding;

        }

        

    void Fire()

        {

            GameObject missile = Instantiate(projectile, transform.position, Quaternion.identity);   

            missile.GetComponent<Rigidbody2D>().velocity = new Vector3(0, projectileSpeed, 0);   

        }

        void Update () {

            if(Input.GetKeyDown(KeyCode.Space))

            {                

                InvokeRepeating ("Fire", 0.000001f, firingRate);

            }

            if (Input.GetKeyUp(KeyCode.Space))

            {

                CancelInvoke ("Fire");

            }

            if(Input.GetKey(KeyCode.LeftArrow)){

                transform.position = new Vector3(

                    Mathf.Clamp(transform.position.x - speed * Time.deltaTime, xmin, xmax),

                    transform.position.y, 

                    transform.position.z 

                );

            }else if (Input.GetKey(KeyCode.RightArrow)){

                transform.position = new Vector3(

                    Mathf.Clamp(transform.position.x + speed * Time.deltaTime, xmin, xmax),

                    transform.position.y, 

                    transform.position.z 

                );

            }

        // restrct player to the gamespace

            float newX = Mathf.Clamp (transform.position.x, xmin, xmax);

            transform.position = new Vector3(newX, transform.position.y, transform.position.z);

            }

        void OnTriggerEnter2D(Collider2D  coll) 

        {                

            Projectile missile = coll.gameObject.GetComponent<Projectile>();   

            if (missile) 

            {

                Debug.Log("Hit by projectile");

                health -= missile.GetDamage();   

                missile.Hit();   

                if (health <= 0) 

                {                 

                Destroy (gameObject);

                } else {

                Debug.Log (" Shot was null");

                }

            }

        }

}

Hi William,

Are you sure? Could it be that they are being spawned but colliding with the player or enemy that is actually firing them, and then being destroyed?

In order to work this out;

  • check you don’t have any errors in the console
  • check your scripts are actually attacked to the correct GameObjects
  • check that you have your prefabs referenced in your script components (via the Inspector) where appropriate
  • run the game

If the behaviour is the same;

  • add a Debug.Log statement to the methods which you believe should be executing so that you can test if they are by viewing the console. For example, you are going to press Space and expect the Fire method to execute, so pop a Debug.Log statement in there, perhaps outputting “Space was pressed”.
  • run the game

Did you see this message in the console? If so, great, remove it and place it in the next place you would expect to see it. At some point you will get to the OnTriggerEnter2D methods, if this generates an output then you know that your projectiles are being spawn and that they are colliding. As a further test you could output the name of the colliding object using;

Debug.Log("Object name : " + coll.gameObject.name);

This will then tell you the name of what the projectile has collided with, I suspect, this may turn out to be the enemy and the player.

If this is the case, you need to adjust where the spawning of the projectile is going to occur from so that it is just in front of the enemy or player (e.g. there is a small gap). An alternative would be to add a check in the OnTriggerEnter2D methods to ignore the collision if it is not the one you are interested in, e.g. if the player is hit by a player missile, ignore it…

If it’s none of the above… come back to me :slight_smile:

Rob,

I’ve got beams coming from the Player ship and the enemy ships. However, they appear to lack velocity. I’ll check using the Debug.Log suggestions you made in your last email. I’m making progress and will call it a night and resume in the morning.

Thanks.

All the best,

William

Rob,

Good morning. I’ve used the Debug.Log in various places in both the enemybehavior and the playercontroller scripts. In both scripts the void OnTriggerEnter2D(Collider2D coll) fails to register in the console. I’ve placed the debug phrase as the top line, before the if missile line and as an else line after destroy gameObject. Not one return in the console. So my void OnTrigger area is not working at all.

Know I truly appreciate this teaching you are providing. I’ll continue to review the manual and see if I can come up with something. In the meantime I look forward to your suggestions.

All the best,

William

Hi William,

Ok, so if nothing is being output from the OnTriggerEnter2D methods then no collision is taking place.

Just so that I am up to date, as the problem has changed since your first post, what is the current issue?

Rob,

I just discovered that the line;

beam.GetComponent<Rigidbody2D>().velocity = new Vector3(0, projectileSpeed, 0);

has no effect on the beams spawned by the player and the enemy. the projectiles just hang out at the point spawned no movement toward either the player or the enemy. There is no collision because the projectiles are not moving.

All the best,

William

Can you paste your scripts up again, as they are at the moment.

Also, please check these scripts are attached to the GameObjects/Prefabs.

Rob,

Rob,

I’ve checked the game objects.

The Controller Script is attached to the Player

the Enemy Behavior script is attached to the Enemy;

both beams have the projectile script attached;

all rigidbodies are ticked kinematic and use full kinematic contact,

enemy and both beams are using box colliders and ticked as triggers;

Player uses a polygon collider and it is ticked as a trigger;

Should the player and the enemy have both controller and enemy behavior scripts attached?

Like wise should the beams have the projectile script and their appropriate player/enemy script attached?

Thanks again for your help.

All the best,

William

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class Controller : MonoBehaviour {

        public GameObject projectile;

        public float projectileSpeed = 10f;

        public float firingRate = 0.2f;        

        public float speed = 15.0f;

        public float padding = 1f;

        public float health = 250f;

        private float xmax;

        private float xmin; 

        

    void Start()

        {            

            float distance = transform.position.z - Camera.main.transform.position.z;

            Vector3 leftmost = Camera.main.ViewportToWorldPoint (new Vector3 (0, 0, distance)); 

            Vector3 rightmost = Camera.main.ViewportToWorldPoint(new Vector3(1,0,distance));

            xmin = leftmost.x + padding;

            xmax = rightmost.x - padding;

        }

        

    void Fire()

        {            

            Vector3 offset = new Vector3 (0, 1, 0);

            GameObject beam = Instantiate(projectile, transform.position + offset, Quaternion.identity);

            beam.GetComponent<Rigidbody2D>().velocity = new Vector3(0, projectileSpeed, 0);

            Debug.Log("Player Missiles away");

        }

        void Update () {

            if(Input.GetKeyDown(KeyCode.Space))

            {                

                InvokeRepeating ("Fire", 0.000001f, firingRate);

            }

            if (Input.GetKeyUp(KeyCode.Space))

            {

                CancelInvoke ("Fire");

            }

            

            // move the player left and right in the gamespace

            if(Input.GetKey(KeyCode.LeftArrow)){

                transform.position = new Vector3(

                    Mathf.Clamp(transform.position.x - speed * Time.deltaTime, xmin, xmax),

                    transform.position.y, 

                    transform.position.z 

                );

            }else if (Input.GetKey(KeyCode.RightArrow)){

                transform.position = new Vector3(

                    Mathf.Clamp(transform.position.x + speed * Time.deltaTime, xmin, xmax),

                    transform.position.y, 

                    transform.position.z 

                );

            }

        // restrct player to the gamespace

            float newX = Mathf.Clamp (transform.position.x, xmin, xmax);

            transform.position = new Vector3(newX, transform.position.y, transform.position.z);

            }

        void OnTriggerEnter2D(Collider2D coll) 

        {                            

            Projectile missile = coll.gameObject.GetComponent<Projectile>();            

            if (missile) 

        {                

                health -= missile.GetDamage();   

                missile.Hit();   

                if (health <= 0) 

                    {                 

                        Destroy (gameObject);

                    } 

            }

        }

}
using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class EnemyBehavior : MonoBehaviour {

    public GameObject projectile;

    public float projectileSpeed = 10.0f;

    public float health = 150f;

    public float shotsPerSeconds = 0.5f;

    private Controller controller;

    void Update ()

    {

        float probability = Time.deltaTime * shotsPerSeconds;

        if (Random.value < probability) {

            Fire ();    

        }

    }

        void Fire ()

        { 

        Vector3 startPosition = transform.position + new Vector3 (0, -1, 0);

        GameObject missile = Instantiate (projectile, startPosition, Quaternion.identity);

        missile.GetComponent<Rigidbody2D>().velocity = new Vector2 (0, -projectileSpeed);

        Debug.Log (" Enemy Missile away");

        }

        

    void OnTriggerEnter2D(Collider2D coll)

        {        

        

        Projectile missile = coll.gameObject.GetComponent<Projectile>();              

            if (missile) 

            {

                health -= missile.GetDamage();              

                missile.Hit(); 

                if (health <= 0) 

                { 

                    Destroy (gameObject);

                }

        }

    }

}

Hi,

From the code perspective, the two things which stand out are;

  • many cases where you are using a float (Vector2 / Vector3), you are not including the f on the end
  • in the Fire methods, you are not casting the instantiated object as a GameObject, e.g.
GameObject missile = Instantiate (projectile, startPosition, Quaternion.identity) as GameObject;

instead of;

GameObject missile = Instantiate (projectile, startPosition, Quaternion.identity);

(and the same for Beam)

Regarding your questions, from memory, you place the Projectile script on the lasers, the ones for both player and enemy GameObjects. PlayerController would be on the Player GameObject and the EnemyBehaviour script would be on the Enemy GameObjects.

Make the above changes, if you still have no success, please zip up the project files and provide me with a URL in your reply where I can download your project from and I will take a look. The forum has a limit of 10mb for files uploaded, so as Laser Defender will be larger than that, use Google Drive or Dropbox etc and just paste in the URL for me.

Rob,

Got it to work!!! I had to build it fro the beginning but I got it with your help. The issue is with the rigidbody2D. Your given tow boxes to tick. One is the Simulate which keeps the rigidbody in the physics simulation. The other is the Use Full Kinematic Contact. Not sure what it exactly does. I had these configured incorrectly. I needed to tick the Simulate box and leave the Use Full Kinematic open.

One question, I’m new to coding and C#. Any suggestions how I can get a better understanding of the structure of C#?

Thanks again for your help.

All the best,

William

Guessing this is a newer version of Unity than the one used in the course then, glad you have it resolved anyway! :slight_smile:

One question, I’m new to coding and C#. Any suggestions how I can get a better understanding of the structure of C#?

Well, there are of course these courses, then YouTube / books and all the normal routes like that, it would really depend I think on how you learn best. For example, if I just turn pages in a book and work through, I don’t tend to retain information as well as if I think of perhaps something I want to create and then have a go at it. During that process, I will invariably come up against challenge after challenge, but I will then go in search of solutions to each challenge and retain the information much better.

Everyone will be different, so I don’t think I could really advise on that, other than to perhaps consider how you feel you learn best and then approach from that direction. If you’re not too sure, try a small variety of different approaches and see which works best for you.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms