Bullet only sometimes detects collission with enemy

Hello!

I have a script for a bullet and a health script for the enemy. When i fire the bullet hitting the enemy it is suppose to take away a portion of the enemy’s health. It only does this sometimes though. I have disabled all the other scipts on the enemy but it wont make any difference.

Here is the bullet script:

using UnityEngine;
using System.Collections;

public class B308 : MonoBehaviour {

	public float BulletSpeed;
	private int damage;
	public int DamageMin;
	public int DamageMax;
	public float BulletAge;

	private GameObject firePoint;
	private GameObject zombie;
	private float firePointX;
	private float firePointY;
	private float DestroyTimer;

	void Start () {
	damage = Random.Range (DamageMin, DamageMax);
	Debug.Log ("Damage of bullet: " + damage);
	firePoint = GameObject.Find("FirePoint");
	this.gameObject.transform.position = new Vector3(firePoint.transform.position.x,firePoint.transform.position.y,0);
	zombie = GameObject.FindGameObjectWithTag ("Enemy");
	}

	void Update () {
	
	this.gameObject.transform.position += -transform.up*BulletSpeed;

	DestroyTimer += Time.deltaTime;

		if (DestroyTimer > BulletAge)
		{
		Destroy(this.gameObject);
		}
	}

	void OnTriggerEnter2D (Collider2D other) {
	if (other.gameObject == zombie)
		{
		Debug.Log ("Zombie Hit");
		Z1Health Z1health = zombie.GetComponent<Z1Health>();
		Z1health.Health -= damage;
		}
	}
}

And the enemy health script:

using UnityEngine;
using System.Collections;

public class Z1Health : MonoBehaviour {

	public int Health;

	void Update () {
	if (Health <= 0)
		{
			Destroy(this.gameObject);
		}
	}
}

After hours of searching i still cant find the bug so i am now turning to the unity community, i hope that you have some tips.

Thank you

//Taegos

Perhaps try like this:

 bool hasAlreadyTriggered = false;
 void OnTriggerStay2D (Collider2D other) {
     if (other.gameObject == zombie && !hasAlreadyTriggered)
     {
         Debug.Log ("Zombie Hit");

         hasAlreadyTriggered = true;
         Z1Health Z1health = zombie.GetComponent<Z1Health>();
         Z1health.Health -= damage;
     }
 }    

 void OnTriggerExit2D (Collider2D other) {
      hasAlreadyTriggered = false;
 }

Check out OnTriggerStay2D doc. This way if you have a time frame problem it should resolve then.

Why don’t your draw a RayCast from the front of the bullet towards the player.

This will allow you to see if there is a direct line of sight and you can visually see the Raycast as well.

var fwd = transform.TransformDirection(Vector3.forward); //casts our raycast in the forward direction
 
var hit : RaycastHit;

//drays our raycast and gives it a green color and a length of 10 meters
Debug.DrawRay(transform.position, fwd * 10, Color.green); 

Once you’ve got the bullet moving towards the player you can see if it hits it.

if(Physics.Raycast(transform.position, fwd, hit, 10)){

     // check to see if the hitobject is the player

Here’s a script I found long ago. I modified it and it works pretty well. If you find that the rigidbody of the projectile pushes other rigidbodies away, either ignore the code related to collision or set it up a trigger system.

This script goes on the Projectile prefab.

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

public class Projectile: MonoBehaviour {

	public int damage = 1;
	public float speed = 1f;
	public float lifeTime = 5f;

	public bool move;
	public GameObject user;
	private LayerMask layerMask;
	private float skinWidth  = 0.1f; //probably doesn't need to be changed 
	private float minimumExtent; 
	private float partialExtent; 
	private float sqrMinimumExtent; 
	private Rigidbody myRigidbody;
	private Vector3 lastPosition;
	private float t = 0f;
	private bool impacted = false;

	void FixedUpdate() {
		if(move == true) {
			t += Time.deltaTime;

			transform.Translate(transform.forward * speed * Time.fixedDeltaTime, Space.World );
			
			Vector3 direction = transform.position - lastPosition;
			Ray ray = new Ray(lastPosition, direction);
			RaycastHit hit = new RaycastHit();
			if (Physics.Raycast(ray, out hit, direction.magnitude, layerMask))	{
				if(hit.collider.transform.root.gameObject == user) {
					return;
				}
				Collide(hit.collider.gameObject.transform.root.gameObject);
			}
			
			this.lastPosition = transform.position;
		}
	}
	
	void OnCollisionEnter(Collision collision) {
		Collide(collision.collider.gameObject.transform.root.gameObject);
	}

	public void Initialize() {
		myRigidbody = GetComponent<Rigidbody>();
		lastPosition = myRigidbody.position; 
		minimumExtent = Mathf.Min(Mathf.Min(GetComponent<Collider>().bounds.extents.x, GetComponent<Collider>().bounds.extents.y), GetComponent<Collider>().bounds.extents.z); 
		partialExtent = minimumExtent * (1.0f - skinWidth); 
		sqrMinimumExtent = minimumExtent * minimumExtent; 
	}
	
	public void StartProjectile() {
		move = true;
		Destroy(gameObject, lifeTime);
	}

	public void Collide(GameObject other) {
		if(move == false) {
			return;
		}
		
		if(other.transform.root.gameObject == user) {
			return;
		}

		Impact(other.transform.root.gameObject);
		impacted = true;
	}
	
	void Impact(GameObject hitObject) {

        //Deal damage etc.

		Destroy(gameObject);
	}
}

You can use it like this (called from the GameObject that shoots the projectile):

			GameObject projectileObject = Instantiate(yourProjectilePrefab, transform.position, transform.rotation) as GameObject;


			Physics.IgnoreCollision(projectileObject.GetComponent<Collider>(), GetComponent<Collider>());
			Collider[] childrenColliders = GetComponentsInChildren<Collider>();
			foreach(Collider colliderChild in childrenColliders) {
				if(colliderChild.enabled == true) {
					Physics.IgnoreCollision(projectileObject.GetComponent<Collider>(), colliderChild);
				}
			}


			if(projectileObject.GetComponent<Projectile>() == null) {
				projectileObject.AddComponent<Projectile>();
			}

			Projectile projectile = projectileObject.GetComponent<Projectile >();
                    projectile.damage = 100;
			projectile.user = gameObject;

			projectile.Initialize();
			projectile.StartProjectile();

Thanks, i will go with a raycastlike approach :slight_smile: