Enemy not taking damage from bullet

This is the first time doing this, but I’m having difficulty getting my enemy to take damage from my bullet/projectile. I have a Capsule Collider added to my bullet, along with a HurtEnemy script, and I have a Capsule Collider and EnemyController script added to my enemy. The bullet appears to be going through my enemy, but it’s health isn’t depleting in the Inspector, nor is it flashing after taking damage. I’ve even tried setting the Is Trigger box on both colliders to active as well.

These are the scripts I have set up at the moment:

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

public class EnemyController : MonoBehaviour
{
    public Animator anim;
    public float moveSpeed;
    public float rotSpeed;
    public bool moveLeft;
    public bool canMove;
    public Transform target;
    public Transform startPoint;
    public int maxHealth;
    public int currentHealth;
    public float invincibilityLength;
    public Renderer enemyRenderer;
    public float flashLength;

    private Transform thePlayer;
    private float invincibilityCounter;
    private float flashCounter;
    //private CharacterController controller;

    void Start()
    {
        thePlayer = GameObject.FindGameObjectWithTag("Player").transform;
        canMove = true;
        anim = GetComponent<Animator>();
        currentHealth += maxHealth;
        //controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (invincibilityCounter > 0)
        {
            invincibilityCounter -= Time.deltaTime;
            flashCounter -= Time.deltaTime;
            if (flashCounter <= 0)
            {
                enemyRenderer.enabled = !enemyRenderer.enabled;
                flashCounter = flashLength;
            }
            if (invincibilityCounter <= 0)
            {
                enemyRenderer.enabled = true;
            }
        }
        if (canMove)
        {
            if (moveLeft)
            {
                transform.position = Vector3.MoveTowards(transform.position, startPoint.position, moveSpeed * Time.deltaTime);
                transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 270f, 0f), rotSpeed * Time.deltaTime);
            }
            else if (!moveLeft)
            {
                transform.position = Vector3.MoveTowards(transform.position, target.position, moveSpeed * Time.deltaTime);
                transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.Euler(0f, 90f, 0f), rotSpeed * Time.deltaTime);
            }
            if (transform.position == target.position)
            {
                anim.SetBool("isFloating", true);
                anim.SetFloat("Speed", 0.2f);
                moveLeft = true;
            }
            else if (transform.position == startPoint.position)
            {
                anim.SetBool("isFloating", true);
                anim.SetFloat("Speed", 0.2f);
                moveLeft = false;
            }
        }
    }
    public void HurtEnemy(int damage, Vector3 direction)
    {
        if (invincibilityCounter <= 0)
        {
            currentHealth -= damage;
            if (currentHealth <= 0)
            {
                Destroy(gameObject);
            }
            else
            {
                invincibilityCounter = invincibilityLength;
                enemyRenderer.enabled = false;
                flashCounter = flashLength;
            }
        }
    }

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

public class HurtEnemy : MonoBehaviour
{
    public int damnageToGive = 10;

    public void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.CompareTag ("Enemy"))
        {
            Vector3 hitDirection = other.transform.position - transform.position;
            hitDirection = hitDirection.normalized;
            FindObjectOfType<EnemyController>().HurtEnemy(damnageToGive, hitDirection);
            Debug.Log("Enemy hit");
        }
    }
}

The debug log doesn’t show either. :-\

Anyone…? I’m struggling with this. I haven’t done it before, so I’m not sure what to do. :frowning:

Hello there.

My opinion, the error is to use ‘OnCollisionEnter’ on a GameObject like a bullet that will move at high velocity.
Usually Unity physics will not detect that collision simply because the bullet is going too fast.

I advice you to use Raycasts which is really the best way to go with this sort of things (they’re also very easy to pick up).
Also, using a lot of physics colliders and that type of calculations (when shooting repetitly) is very bad on performance wise.

Plus, i would modify that line which is really bad for performances

FindObjectOfType<EnemyController>().HurtEnemy(damnageToGive, hitDirection);

With

other.GetComponent<EnemyController>().HurtEnemy(damageToGive, hitDirection);

Or even better, code it in the way that you don’t have to call GetComponent at all.

Cheers!

Now I’m having issues setting up Raycasts. They’re not something I’ve used before. Also, using GetComponent has caused a lot of confusion for me before as I’ve been told they’ll only get a component on the GameObject the script is attached to. But making a reference to another object isn’t working. This is just causing more frustration and confusion. :frowning:

So now I have these in my PlayerController script…

private HurtEnemy damageEnemy;

void Start()
{
damageEnemy.GetComponent<HurtEnemy>();
}

void Update()
{
if (attack)
        {
            anim.SetTrigger("Attack");
            damageEnemy.Shoot();
        }
}

And this in my HurtEnemy script:

public class HurtEnemy : MonoBehaviour
{
    public int damnageToGive = 10;
    public float range = 50;
    public GameObject rayProjectile;

    public void Shoot()
    {
        RaycastHit hit;
        if(Physics.Raycast(rayProjectile.transform.position, rayProjectile.transform.forward, out hit, range))
        {
            Debug.Log(hit.transform.name);
        }
    }
}

This causes my character to just jump on the spot and gives me the error ‘Object reference not set to an instance of an object’.

GetComponent<HurtEnemy>();

Returns the ‘HurtEnemy’ component of the GameObject where this script is attached

public GameObject anotherGameObject;
anotherGameObject.GetComponent<HurtEnemy>();

Returns the ‘HurtEnemy’ component present on the GameObject ‘anotherGameObject’.

‘Object reference not set to an instance of an object’ come out when you don’t assign a reference to a variable and try to use it (or when you firstly try to use it, and later assign the reference).

private HurtEnemy damageEnemy;
void Start()
{
damageEnemy.GetComponent<HurtEnemy>();
}

This is totally wrong.
You’re trying to get a component from another component not assigned.

If the reference you’re trying to assign to ‘damageEnemy’ is on the same GameObject where the player script is, change it in:

private HurtEnemy damageEnemy;
void Start()
{
damageEnemy = GetComponent<HurtEnemy>();
}
void Update()
{
if (attack)
        {
            anim.SetTrigger("Attack");
            damageEnemy.Shoot();
        }
}

You’ve totally lost me. I don’t think I’m ever going to get my head around this. :frowning: This is not the first time I’ve been confused with the ‘Object reference not set to an instance of an object’ error and using GetComponent.

EDIT: Okay, I’ve got it …for now. Though I swear I’ve made references to scripts on other game objects in the past, added them in the Inspector, used GetComponent, and I’ve still had the error. :-\

See, even now, I’ve had the same crap. I’ve made a public reference to my HealthManager called theHealthManager in my ScreenFader script, I’ve used theHealthManager = GetComponent(); in the Start function so I can check the player’s health, I’ve added the GameObject with the HealthManager script attached to it in the Inspector for the Screen Fader GameObject and I still get the ‘Object reference not set to an instance of an object’ error. This is what I mean when I say I don’t think I’ll ever get my head around it. It confuses the hell out of me so much. This is why I prefer to use FindObjectofType; it doesn’t give me the same issues. :frowning:

Please, stop whatever you’re doing and check out the very basic tutorials with the very basic information, for example how to hold reference to another scripts.

https://www.youtube.com/watch?v=PBqTrK3z_KM

1 Like

Thanks for the video. Still a bit confused though. I’ll probably need to watch the video a few times.

So, my take away from that… Am I right in saying, that whenever I try to get a component on another GameObject, I use a private variable and reference the script on another GameObject, make a public reference to the GameObject the script is attached to so it can be dropped into the Inspector, but when calling GetComponent, I have to reference the name/variable of the GameObject so it’s something like:

public GameObject projectile;

private HurtEnemy damageEnemy;

void Start()
    {
    damageEnemy = projectile.GetComponent<HurtEnemy>();
    }

?

Okay, following Brackey’s tutorial, I’ve got the projectile working and the enemy takes damage and flashes, but it happens as soon as Space is pressed and waaaay before the projectile even reaches the target. I suppose the easiest thing to do is scrap the projectile completely, but I would prefer to keep it. Not sure how I could rectify this issue.

Another problem I’m having is that if the Space key is pressed using GetKey, my shooting animation plays twice and the target is hit no matter what the range is set to. If I change GetKey to GetKeyUp/Down, the shooting animation plays once, but it never registers the enemy being hit. Not unless the button is mashed. And again, the range has no effect.

Do not care about your projectiles and whatnot. Watch AND follow along the basic tutorials. If you’re confused with the most basic thing you can imagine in Unity, what you will do when you really need to do anything for yourself? Just think about it. If you lack of the basics you will stuck and you will give up sooner or later. And you don’t want to give up, do you?

I do care about the projectiles. This is for a college assignment that’s due on Monday. At times, these forums remind me too much of my current situation with trying to get mental health support. There’s either no help or I’m expected to just help myself. >_> And my question regarding the GetComponent thing still hasn’t been answered… Was my take away even correct…?

Apologies if I come across as moody, but I really am in a bad mood at the moment.

You’re on the right way. But it is simpler than you think. GetComponent returns a component on the GameObject you choose (if the component exsists on that gameobject). It is just a way to access other components. There isn’t so much to say/question about it.

In your case, instead of using a public GameObject reference and a private to a component you could make the Component public or use the attribute [SerializeField] on the variable, like that:

[SerializeField]
private HurtEnemy damageEnemy;

Now if you look at the inspector you will be able to assign the reference by dragging and dropping it.
In poor words [SerializeField] allows you to show and assign a reference from the inspector of a private variable.

I agree with @ , even if i’ve started just like you, by writing code without sense on my first programming experience, i’ve only caused myself a lot of headache and feelings to give up, it would have been one hundreds time better learning all i could first before opening Unity, i could have saved so much time.
I had the motivation to go forward all and restart from zero multiple times, i hope you will do the same.

Sadly we can’t inject you motivation or good feelings. On Google you can find everything about the meaning and usage of GetComponent and that’s why not so many people respond to this thread, because everything has been already said. And this values for the majority (if not all) of things you could need to do in Unity.

And please, don’t say that there is no help, that’s the wrongest thing you could ever say about this community.
Start by the playlist @ has attached, for any doubts, google them. If you are sure they aren’t on google, create a thread.

Good luck.

But this is the same issue as I mentioned above - there are times where I’ll seemingly do that. I’ll make the component public, use GetComponent, and then drop the reference in the Inspector, but still get an error saying ‘Object reference not set to an instance of an object’. It’s that that completely throws me a curveball. :-\

I think due to my Asperger’s I tend to have difficulty processing certain things. I’ll usually do a Google search on how to implement something and it either doesn’t make sense, isn’t explained very well, or is just too overwhelming to understand. I prefer things to be broken down into stages and explained clearly.

Well, then good luck. You know, you don’t have to listen to our advice. Apparently you know better. Hope you’ll be doing great.

Still struggling to get my head around it all. So, what you’re saying is, GetComponent should only be used in a script that’s attached to the object that has the component, otherwise, if a script/object doesn’t have it, don’t use GetComponent, and just use a public variable referencing the component and drop it into the Inspector…?

I do try to do this at times. Often though I feel so lost and unsure how I’d go about setting the code up and getting it to work that my first instinct is to ask for help; I end up feeling totally lost and directionless and then get frustrated when I get no reply or the responses are even more vague and confusing.

Also, this is for a third-person shooting mechanic. I’ll try and take your advice and break it down. See how I get on.

If you stick to the approach that you are describing here, that should generally work, but these are not hard, fast rules by any means.

Instead of just memorizing “in this situation i do this and in that situation i do that” you’ll eventually want to develop a better understanding of what these methods actually mean and do. Then it won’t be confusing at all.

1 Like

You’re getting closer. You may not want to use GetComponent and instead using public access.
But you may need to use GetComponent when you want, for example, instantiate a Prefab from a script and modify a variable of a component present on that prefab.

Let’s say you have a Prefab that we will call “PrefabToInstantiate” you want to instantiate.
This Prefab has a component ‘ItemInstantiated’ that has a public int “someValue”.
Here is the component:

public class ItemInstantiated: MonoBehaviour
{
public int someValue = 0;
}

From another script, we’ll call it ‘Instantiator’ we want to instantiate “PrefabToInstantiate” and set the value of “someValue” to 10.

public class Instantiator: MonoBehaviour
{
// Reference to the Prefab, to drag and drop from the inspector
public GameObject PrefabToInstantiate;

void Start()
{
// Here  we create an instance of the reference 'PrefabToInstantiate'
GameObject newItem = Instantiate(PrefabToInstantiate, transform.position, transform.rotation);
}
}

Until here we’ve just spawned the copy of the Prefab in the scene, we haven’t accessed yet to the component.
Now we know for sure that ‘newItem’ has a component “ItemInstantiated”, because the prefab assigned at ‘PrefabToInstantiate’ has it, and newItem is a copy of the prefab.

So all we have to do is to modify the Start function to:

void Start()
{
// Here  we create an instance of the reference 'PrefabToInstantiate'
GameObject newItem = Instantiate(PrefabToInstantiate, transform.position, transform.rotation);
// We get the Component of the instantiated item, then we access the 'someValue' variable and modify its value
newItem.GetComponent<ItemInstantiated>().someValue = 10;
}
}

I hope this can help you.

1 Like

Thanks for this. That clears things up a bit. I have a slightly better understanding now. I’ll bookmark this thread for future reference. :slight_smile: