i’m currently working on a 2d stealth game, and so i’ve designed a method, which is suppose to see if the enemy can or can’t see the player at any given time.
but the problem is that whenever i try to run the program, it fails on the very first line in the method, saying that quote “NullRefrenceException: Object refrence not set to an instance of an object” i’ve tried to see if maybe the direction calculation is off, or maybe it wants me to change the location at which the method calculates the direction but i just can’t figure it out.
A NullReferenceException occurs when you have an object variable which does not contain an object. This can be the case because you did not yet assign an object instance, because the returned object from some method itself was “null”, or because the object you assigned does not exist anymore. If you now try to access some property from inside such an object, that’s when the compiler throws you a NullReferenceException. It’s probably the most common problem you encounter, especially as a new programmer.
Example:
SomeObject reference;
reference.someIntegerValue = 5; // <-- throws an Exception since 'reference' does not contain anything, thus the compiler has no idea where in memory to write that '5' to.
If the problem occurs in the first line of the above posted method, then ‘player’ is likely null. I assume you meant to assign it through the inspector, but since you did not post the rest of the class i cant know how player is supppsed to be assigned. Generally speaking, it is helpful to post the entire script (unless it’s hundreds of lines long, in which case you may wanna trim it by removing unrelated methods). Along the same line of thought, you generally want to post the entire error message, including the line it occurs on - and if the script is not identical, note what line of the example the line in the error corresponds to. For posting problems productively you may wanna have a read here: How to report a problem in the Unity3D forums – PLBM Games
Ok, so i checked, and you’re absolutely right the player was apperantly null, which is why it didn’t work, so now how can i make sure that the player isn’t null, so that way the method will run it’s course the way it’s supposed to?
Also if you want i can post the player’s control script.
To make sure the player is not null, you have to assign an instance of the player script to your player variable.
We wont need to see the player script, but it would be helpful to know where you intend to get your player reference from. Some object in your scene will have the “Player” script attached to it (or whatever the type of your ‘player’ variable is called. Since i cant see the declaration, i’m assuming it’s a Player type).
If that script is on the same gameobject as the script you posted above, you probably intended to set it through GetComponent in Start(), so something like that: player = GetComponent();
If, on the other hand, the player script is on some other gameobject, you probably wanted to assign the reference through the inspector via drag and drop. For that your ‘player’ variable has to be public.
Hope this helps. If it does not, please post the full above script in your next reply and explain what you are attempting to do in a general sense, as well as where you intend to get the reference for ‘player’ from.
Ok i don’t really get what i have to do if the player script is on another game object, i got the fact that i’m suppose to have a public variable for the player which i then drag and drop the player object into in the inspector, and i have that, and i did that. But according to the debug log it still thinks of the player variable as null, which in term doesn’t allow me to check if the enemy is supposed to see the player or not. So i’m just gonna upload the entire enemy control script and then try to explain what i’m trying to do.
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices.ComTypes;
using Platformer.Gameplay;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEngine.Video;
using static Platformer.Core.Simulation;
namespace Platformer.Mechanics
{
/// <summary>
/// A simple controller for enemies. Provides movement control over a patrol path.
/// </summary>
[RequireComponent(typeof(AnimationController), typeof(Collider2D))]
public class EnemyController : MonoBehaviour
{
public int DetectionRange;
public int DetectionAngle;
private bool temp;
public Visability visability;
public PlayerController player;
public PatrolPath path;
public AudioClip ouch;
internal PatrolPath.Mover mover;
internal AnimationController control;
internal Collider2D _collider;
internal AudioSource _audio;
SpriteRenderer spriteRenderer;
public Bounds Bounds => _collider.bounds;
public bool CanSee;
void Awake()
{
control = GetComponent<AnimationController>();
_collider = GetComponent<Collider2D>();
_audio = GetComponent<AudioSource>();
spriteRenderer = GetComponent<SpriteRenderer>();
}
void OnCollisionEnter2D(Collision2D collision)
{
var vplayer = collision.gameObject.GetComponent<PlayerController>();
if (vplayer != null)
{
var ev = Schedule<PlayerEnemyCollision>();
ev.player = vplayer;
ev.enemy = this;
}
}
private void Detection()
{
if (player != null)
{
CanSee = false;
Debug.Log("this is testing");
Vector3 dirtoplayer = player.transform.position - transform.position;
RaycastHit2D raycasthit2d = Physics2D.Raycast(transform.position, dirtoplayer, DetectionRange);
var Meter = GetComponent<Visability>();
if (Vector3.Distance(transform.position, player.transform.position) < DetectionRange && !player.IsSneaking)
{
if (control.move.x > 0)
{
if (player.transform.position.y - transform.position.y < player.transform.position.x - transform.position.x &&
-player.transform.position.y + transform.position.y < player.transform.position.x - transform.position.x)
{
if (raycasthit2d.collider != null)
{
if (raycasthit2d.collider.gameObject.GetComponent<PlayerController>() != null)
{
CanSee = true;
}
}
}
}
else if (control.move.x < 0)
{
if (player.transform.position.y - transform.position.y < -player.transform.position.x + transform.position.x &&
player.transform.position.y - transform.position.y < player.transform.position.x - transform.position.x)
{
if (raycasthit2d.collider != null)
{
if (raycasthit2d.collider.gameObject.GetComponent<PlayerController>() != null)
{
CanSee = true;
}
}
}
}
}
}
}
void Update()
{
Debug.Log(CanSee);
if (CanSee != temp)
{
temp = CanSee;
visability.recieve = CanSee;
}
if (path != null && !temp)
{
if (mover == null) mover = path.CreateMover(control.maxSpeed * 0.5f);
control.move.x = Mathf.Clamp(mover.Position.x - transform.position.x, -1, 1);
}
}
}
}
keep in mind i slightly updated the method cause i got the sense that you think i’m a first time programmer, which is sort of embarrasing. but anyways, i’m trying to make a 2d stealth game, in which the enemies will walk around in a left/right like movement and then if they see the player in a 90 degree cone they’ll then stop moving and send a true/false value to the visability meter, then after a certain amount of time that the player is visible the meter will activate the death script and you’ll have to start the level all over again (the part about activating the death script and all of that isn’t part of the enemy script above but rather part of a seperate script).
keep in mind that whilst it’s not my first time programming, it is my first time working with unity. and so i made most of the parts in this script by dismantling the free unity example enemy controller platformer script and then reasembling it with some other stuff.
Sorry about that. It can be hard to tell sometimes whether someone is new to programming or just new to Unity. And nullreference exceptions as well as methods with 10 or so return true/false statements are indicators for being rather new to programming, but i didnt mean to assume anything.
Which of those assumptions are correct and which not?
Your enemies exist in the scene from the beginning and are not being spawned
You did drag the gameobject containing the PlayerController component into the inspector field of your EnemyController on your enemie(s)
It is correctly shown there afterwards, even after you press play
Since ‘player’ supposedly is still null, your Debug.Log message “this is testing” is not being printed? Make sure you check the console and dont use filters there!
Since you check for player != null at the beginning now, there is no exception anymore, right?
If the first 3 assumptions are correct, the fourth one is curious. If you have multiple enemies in the scene, maybe you forgot to add it to them all? In that case, or if you spawn the enemies in automatically at some point, you may wanna automate the process of finding the player reference - for example by having it globally available using a singleton pattern.
I have 1 enemy since i’m first testing to see if the mechanism works, then i start adding more and more enemies, but besides that all of you assumptions are correct, except for the 3rd one since i didn’t get what you meant by that.
I was just asking if the inspector still displays the object reference in that field after pressing play. An exception or some other occurance may remove it at runtime, even tho i dont know how that would happen in this case. If the inspector does still display the reference and the player object reference is still considered null i’m honestly not sure why that is.
How are you calling Detection()? The method is private but you are not calling it from within the EnemyController script.
Oh shit, i forgot to call the function in the update after i added to changes to the method. Wow that is extreemly embarrasing. Ok so thank you very much for the help, i’m gonna go debug some other stuff that i know how to debug, and again thank you. But i’m gonna leave this thread open for a bit in case i’ll have any other problems i can’t figure out. again thanks.
Expect to see this error a LOT. It’s easily the most common thing to do when working. Learn how to fix it rapidly. It’s easy. See the above link for more tips.
yea the other guy already helped with that, i’m just leaving this thread open for a bit in case i run into more trouble, but the problem itself is solved.