Hi
I´ve been stuck on this code for a few days, I´ve reviewed the video and compared the script to others on this forum but can´t get it to work. I believe I have identified the error but do not understand why the error occurs.
Below is the Weapon.cs script
Basically, DamageEnemy is not being called because enemy remains null.
You´ll notice that I´ve included a few Debug.Log lines in order to see how far it goes. In the console I get the following printouts:
We hit AlienSpaceship and did 1000 damage.
AlienSpaceship
Null
So, if: Enemy enemy = hit.collider.GetComponent();
Why is enemy Null?
if I change: if(enemy != null) to if(enemy == null), then DamageEnemy is called.
My AlienSpaceship has the following components attached: Transform, SpriteRenderer, Seeker (Script), Rigidbody 2D, Enemy AI(script) Circle Collider 2D.
I am running:
Unity Version 2018.3.4f1 Personal
Visual Studio Version 19.9.4
Weapon.cs
using UnityEngine;
using System.Collections.Generic;
using System.Collections;
public class Weapon : MonoBehaviour
{
public float fireRate = 0;
public int Damage = 10;
public LayerMask whatToHit;
public Transform BulletTrailPrefab;
public Transform MuzzleFlashPrefab;
float timeToSpawnEffect = 0;
public float effectSpawnRate = 10;
public float lifeTime;
float timeToFire = 0;
Transform firePoint;
// Use this for initialization
void Awake()
{
firePoint = transform.Find(“FirePoint”);
if (firePoint == null)
{
Debug.LogError(“No firePoint? WHAT?!”);
}
}
// Update is called once per frame
void Update()
{
if (fireRate == 0)
{
if (Input.GetButtonDown(“Fire1”))
{
Shoot();
}
}
else
{
if (Input.GetButton(“Fire1”) && Time.time > timeToFire)
{
timeToFire = Time.time + 1 / fireRate;
Shoot();
}
}
}
void Shoot()
{
Vector2 mousePosition = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firePointPosition = new Vector2(firePoint.position.x, firePoint.position.y);
RaycastHit2D hit = Physics2D.Raycast(firePointPosition, mousePosition - firePointPosition, 100, whatToHit);
if (Time.time >= timeToSpawnEffect)
{
Effect();
timeToSpawnEffect = Time.time + 1 / effectSpawnRate;
}
Debug.DrawLine(firePointPosition, (mousePosition - firePointPosition) * 100, Color.cyan);
if (hit.collider != null)
{
Debug.DrawLine(firePointPosition, hit.point, Color.red);
Debug.Log(“We hit " + hit.collider.name + " and did " + Damage + " damage.”);
Debug.Log(hit.collider.name); // This is a test to detect the collision.
Enemy enemy = hit.collider.GetComponent();
Debug.Log(enemy); // This is a test to detect that the enemy was created.
// if(hit.collider.name == “AlienSpaceship”) This is a test
if (enemy != null)
{
Debug.Log(“Inside the loop”); // This is test to detect if inside the loop…
enemy.DamageEnemy(Damage);
Debug.Log(“We hit " + hit.collider.name + " and did " + Damage + " damage.”);
}
}
}
void Effect()
{
Instantiate(BulletTrailPrefab, firePoint.position, firePoint.rotation);
Transform clone = Instantiate(MuzzleFlashPrefab, firePoint.position, firePoint.rotation) as Transform; // why cast?
clone.parent = firePoint;
float size = Random.Range(0.6f,0.9f);
clone.localScale = new Vector3(size, size, 0f);
Destroy(clone.gameObject, lifeTime);
}
}
Use code tags
when you post code. It’s very difficult to read and even harder to discuss in its current form.
Use code tags…
Enemy is null if whatever your raycast hit didn’t have an Enemy component on it. Are you sure you have an Enemy component on what your raycast hit? (note you said it has Enemy AI, but your getComponent is for Enemy. Are these 2 different scripts?)
Hi
I´m sorry but its the first time I post and I´m learning as I go. I hope I´m using the correctly below.
Yes I have an Enemy code, please see below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[System.Serializable] // This is so we can see the contents of the class
public class EnemyStats
{
public int Health = 100;
}
public EnemyStats stats = new EnemyStats();
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void DamageEnemy(int damage)
{
stats.Health -= damage;
if (stats.Health <= 0)
{
GameMaster.KillEnemy(this);
}
}
}
Hi
I´m sorry but its the first time I post and I´m learning as I go. I hope I´m using the correctly below.
Yes I have an Enemy code, please see below
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[System.Serializable] // This is so we can see the contents of the class
public class EnemyStats
{
public int Health = 100;
}
public EnemyStats stats = new EnemyStats();
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void DamageEnemy(int damage)
{
stats.Health -= damage;
if (stats.Health <= 0)
{
GameMaster.KillEnemy(this);
}
}
}
And as I asked, do you just have an Enemy script or do you have an Enemy AI script also? (Can’t tell if they are suppose to be the same script or not or if you actually have one called EnemyAI)
Otherwise, it’s null if it doesn’t find the Enemy script. Are you sure it’s not hitting something else also and you’re just getting your messages mixed up in the console?
I have both an Enemy script and also a separate EnemyAI script which I can post if you wish but I believe the price of code that is troublesome is either the Enemy or the Weapon script. EnemyAI only deals with the movement of the Enemy.
I agree with you that for some reason it is not finding the Enemy script, I just don’t know why…
I create the local variable here: Enemy enemy = hit.collider.GetComponent();
and then I make a reference to it´s DamageEnemy() method
While I un the code, no errors are generated in the console
void Shoot()
{
Vector2 mousePosition = new Vector2(Camera.main.ScreenToWorldPoint(Input.mousePosition).x, Camera.main.ScreenToWorldPoint(Input.mousePosition).y);
Vector2 firePointPosition = new Vector2(firePoint.position.x, firePoint.position.y);
RaycastHit2D hit = Physics2D.Raycast(firePointPosition, mousePosition - firePointPosition, 100, whatToHit);
if (Time.time >= timeToSpawnEffect)
{
Effect();
timeToSpawnEffect = Time.time + 1 / effectSpawnRate;
}
Debug.DrawLine(firePointPosition, (mousePosition - firePointPosition) * 100, Color.cyan);
if (hit.collider != null)
{
Debug.DrawLine(firePointPosition, hit.point, Color.red);
Debug.Log("We hit " + hit.collider.name + " and did " + Damage + " damage.");
Debug.Log(hit.collider.name); // This is a test to detect the collision.
Enemy enemy = hit.collider.GetComponent<Enemy>();
Debug.Log(enemy); // This is a test to detect that the enemy was created.
// if(hit.collider.name == "AlienSpaceship") This is a test
if (enemy != null)
{
Debug.Log("Inside the loop"); // This is test to detect if inside the loop...
enemy.DamageEnemy(Damage);
Debug.Log("We hit " + hit.collider.name + " and did " + Damage + " damage.");
}
}
}
You didn’t say there was an enemy script on what you hit. You said EnemyAI. So either you didn’t mention the enemy script and it was a slip up, or you don’t have one on what your raycast is hitting.
You are exactly right!
I figured it out this morning as soon as I woke up! I said to myself: I know why my code isn’t working!
I do have an Enemy script but I created it in the Project Panel and neglected to add it as a component of the AlienSpaceship Gameobject.
So the reason why it was coming up as Null was because as you said, the Gameobject that I was hitting with the raycast didn’t have an Enemy component!
Thanks for your help