#NullRef bug (reported)
1 messages · Page 1 of 1 (latest)
BrickParent https://gdl.space/ecozeroqiv.cpp
Brick https://gdl.space/cobudaponu.cs
LevelManager https://gdl.space/gidosupexo.cs
Ball https://gdl.space/iqozuwarum.cs
GridManager https://gdl.space/ufilabatet.cs
In the minutes before this error occurred, I was simply adding a Debug.Log() to the Ball's collision exit call
any particular reason you are using FindObjectOfType to get a reference to a singleton? You have a public static reference built right in so just access your LevelManager with LevelManager.Instance
also it seems likely that line 33 in your Brick class is returning null
Oh, that, I decided to make it static after doing that.
Maybe that's the problem
and yes, line 33
I am perplexed
this line has not changed, yet it does seem to return null
this is odd
the error persists, so parent should be null, yet the game executes perfectly like before
This is the logic simplified:
Ball collides with Brick - on Exit, access brick in a static list, use the TakeDamage function with ballDamage input
Brick takes damage, and if 0 or less health, tells the parent it is being destroyed, and disables itself.
The parent then plays the Particle system,
and tells the LevelManager that a Brick has been destroyed, adding to the counter
This should work, and it is working, but I get bogus errors
or, as experience tells me, I could be retarded
I see that you are setting the parent of the brick to the GridManager object when you spawn it. Does that object also have the BrickParent component?
so the brickPrefab object, is that both the parent and brick? if so, just use a serialized reference instead of trying to get the component at runtim
the prefab contains both objects
The grid manager instantiates the prefab, but Names the Parent and the Child - Capitalized and Lower case
the parent of the instantiation, is the Grid parent object
then just use a serialized reference to the parent, no need to get component if you can spawn it with a reference to its parent already
that is a pretty good point
also to make things less confusing and easier to follow the logic, i'd change the brickPrefab field's type to BrickParent so it's a little more obvious what is being instantiated
you don't have to do that, but i find it's just better practice than using GameObject for the prefab type
Noted. I try to be practical and use data types other than GameObject, so I don't have to use GetComponent
in this case, that wasn't directly possible, or maybe with a syntax I haven't considered
new errors now
NullReferenceException: Object reference not set to an instance of an object
Brick.OnEnable () (at Assets/Scripts/Brick.cs:33)
UnityEngine.GameObject:SetActive(Boolean)
LevelManager:NewLevel() (at Assets/Scripts/SO/LevelManager.cs:72)
LevelManager:Awake() (at Assets/Scripts/SO/LevelManager.cs:114)
I have a theory
I think there is something wrong with the way I've set up the static instance of the LevelManager
but also - this all worked without errors. I was simply adding a Debug Log to try to fix the problem of a Brick not being registered as destroyed by LevelManager, if the ball was inside it when a new level spawned
I'm rewriting without static
it's line 33 in the Brick class that is error'd right now, right? Could you tell me what line that is so I can be sure
parent.BrickIsEnabled();
okay then parent is still null
but the score counting works, so it does work, but the editor still says error
did I break my project lol
we'll see if this works first
hmm
NullReferenceException: Object reference not set to an instance of an object
Brick.OnEnable () (at Assets/Scripts/Brick.cs:33)
Note: I did recreate the Bricks with GridManager
private void OnEnable()
{
parent.BrickIsEnabled();
this is apparently the problem
public void BrickIsEnabled()
{
levelManager.BrickSpawned();
}
did you end up making parent a serialized field and dragging the reference in for the prefab?
yes
then I recreated the grid's prefabs
so they are updated
public void BrickDestroyed()
{
bricksBroken++;
bricksRemaining--;
if (bricksRemaining == 0)
{
LevelComplete();
NewLevel();
}
}
public void BrickSpawned()
{
bricksRemaining++;
}
All this works perfectly fine
so why am I getting an error, hmm
If you don't have any other ideas, I'm going to prepare closing about 100 browser tabs before restarting the PC, just in case .Net Framework is derping out
if you want, I can zip you the project
yeah i have no idea. feel free to zip it up and i'll take a look at it if you want
Thanks a lot. I'll do that after restart and test.
the library folder is probably the largest part, you can exclude that folder since it gets rebuilt automatically
ah nice
Let me know if one of the Brick Sprites is Lighter than the others
I saved After recreating the grid, and the asset was deleted, so I'm not sure what's going on here
if it is, just go to the Grid game object and activate the Recreate function by checkbox
also, don't mind the fugly particle system - I just paused that aspect for a while
yeah i have no idea why this is happening. Like it seems to be affecting several specific bricks, because those same bricks are not being destroyed every single time, but i can clearly see in the inspector that the reference is there.
gonna try some breakpoints to hopefully get more info about wtf is going on
doesn't it affect all of them for you?
oh now that i look again, i suppose it does
if the project is "broken" or any of the classes corrupted, that may have happened while I had the LevelManager also have a static instance - was it correct to have it attached to an object at that point?
yeah you would need to have it attached to an object since it's a monobehaviour
alright
So Editor is saying parent.BrickIsEnabled(); doesn't work because of null reference
but the Parent successfully executes BrickIsEnabled(), because the LevelManager is keeping track of the bricks remaining/destroyed
I created MyParent and MyChild, copied the class contents, changed type accordingly, fixed prefab
No change.
it definitely isn't showing the correct numbers for me. Also for some reason d5 seems to be the only brick that is able to be broken and when it breaks, remaining bricks goes to -1 (from 0)
but also, why are you instantiating bricks if they are already in the scene?
your bricks don't break? :S
no, it's because of the nullref, every time a brick is hit it throws the nullref
oh that's my fault, i messed with the levelmanager a bit
To my knowledge, I'm only instantiating them in Editor Mode, once, after setting the parameters.
After that, the objects are simply disabled/enabled
ah well, that part has worked for some time, even seamlessly when I rewrote it for the List approach
and TakeDamage etc
new clue
or mindfuck
I believe I forgot to recreate the grid after fixing the prefab, as previously stated
so I recreated it
but now it gives an error, and it makes no sense
it only spawns one brick
NullReferenceException: Object reference not set to an instance of an object
GridManager.SpawnBricks () (at Assets/Scripts/GridManager.cs:128)
GridManager.Update () (at Assets/Scripts/GridManager.cs:42)
MY bad
ignore
I did this
wait, my bad again
hmm
oh my god, it's class corruption
I implemented the new scripts with cloned code, correctly across the scripts now
no errors
but how can I detect this properly and fix it properly - it's like my project is corrupted now if I can't fix this
Fixed by recreating classes, copying class contents, rewriting scripts to work with new Class/Type name
wait so you were able to fix it by just recreating everything?
Yes, the BrickParent and Brick scripts
I made MyParent and MyChild
copied contents, rewrote scripts for the new names
and it works, no errors!
huh weird
extremely
this has to be a bug
but in C# or Unity
at least I have this zip file and a short description for a solution
Unity should have enough data to work with for a bug report.
Thanks a lot for the assist @bitter grove
Have a nice day o/
NullRef bug (reported)
The bug is actually back
Cleaned up some unused code, and all of a sudden, there were errors again, in the new scripts
currently installing the Unity Editor anew
After installing the latest LTS, upgrading the project and Regenerating Project Files, the error still persists
I have a lot of problems like this too lately. I send a report to unity and am now waiting for answer
I will keep you up to date when I fix it
Thanks a lot, man.
There was a new version out now, up from 23f1 to 24f1
My project was still bugged when I upgraded, but hopefully they fixed -something- for new ones
are you instantiating gameobjects in edit mode and saving references to them in a monobehavior, and expecting those references to persist into play mode?
I'll have a closer look
The grid is sized and filled with Bricks in the Editor
when I enter Play Mode, the Brick components are added to a List in LevelManager
if so, i don't think you can really do that? you could instantiate things from edit mode and then save the scene and they would be there, but i don't think references in monobehaviors will carry over between play sessions
https://docs.unity3d.com/Manual/DomainReloading.html might be the actual culprit of your issue
it is used by Ball in OnCollisionExit2D to select which ball takes the damage, based on Name
you can turn it off, but you have to manage all that stuff yourself
unless I'm misremembering, wasn't the nullref in the OnEnable method for the Brick class and the only object in that method that could be null was the parent object which had a serialized reference
alternately, just spawn the stuff in at runtime
Can you clarify which references you are referring to?
no, because i haven't read through all your code
Alright.
i'm just saying it sounds like that's what you might be doing, so i'm not surprised it's not working
I've explained a few things earlier in this chat. I'll bring a summary down.
you said something about a static list, which is the sort of thing that domain reloading would reset automatically
I gave the LevelManager a static instance at some point, and beyond that everything worked perfectly.
It was first when I added a Debug Log to Ball OnCollision that I suddenly had this error, which cannot be real if the balls actually take damage
In my current project there is no static
I don't really know why you've got so much stuff in OnEnable and Awake triggering cross-objects
yeah, debug.log isn't what caused your error though, so it makes sense to look elsewhere
these two callbacks interweave between objects, you can only rely on them being before each other when called from the same object
indeed, but this bug is reproducable, fixable, and reproducable again
mmm yeah, could just be a race condition which would explain why you only sometimes see it
BrickParent.BrickIsEnabled is called from Brick.OnEnabled which can very well occur before BrickParent.Awake ever does
if you download the project zip (50 MB) and create new scripts called MyChild and MyParent, and copy code from Brick and BrickParent, and rewrite the Class names in the code, and rework the prefab, and recreate the grid - then the bug is gone. But later it appears again \o/
That said, I will for now work with what you are saying.
have you stepped through in the debugger? you can see what order things are executing in and confirm that pretty easily
I see. That may be my problem then.
perhaps this can be solved by disabling the brick in the prefab
you aren't even using the prefab at runtime though
Also, I kinda feel like having ExecuteOnEditMode on GridManager is also asking for trouble
I'm open to a different approach.
Right now the goal is however not perfection, but results.
well what are you trying to solve? why does it execute in edit mode?
I mean, I went back to the singleton, removed ExecuteOnEditMode, and made the bricks spawn in Start
and problem solved afaik
that's how i usually do it, but maybe that's no good, cause you want to see the bricks in the editor or something?
because Start is after Awake, the references are set up, and there's no conflict when trying to find the singleton as it's already set up
damn now i feel dumb for not suggesting that last night
the error is gone?
the only downside there is you can't see your bricks until you press play
but for that i would add a preview button and clean those up before spawning the 'real' ones in playmode, probably?
I'm sure you could fix that by restructuring some other stuff, but I don't have enough understanding of what's going on (nor do I want to) to figure out the 'proper' solution
private void Start()
{
// Get Bricks
bricks.AddRange(grid.GetComponentsInChildren<MyChild>(true));
// Prepare New Level
DisableAllBricks();
NewLevel();
}
I moved this, but the error persists
yeah, my more general advice from skimming this is 'your life will be easier if you have your logic only flow in one direction where possible'
I mean, from the uploaded project I did as I said above
changing GridManager to spawn after awake all I did was a lazy
void Start()
{
recreate = true;
}```
and make sure you delete all the bricks in the scene
this single change to the Grid Manager made all the Null Reference errors in the console go away?
No, it required the other stuff above that I mentioned too
Though I'm unsure what the issue is at Ball.OnCollisionExit2D (UnityEngine.Collision2D collision) in the Find function, I can't debug it properly
but that's separate from the other issues
levelManager.bricks.Find(x => x.name == collision.gameObject.name).TakeDamage(ballDamage);
This line finds the name of the brick from the collision, finds it in LevelManger's public List of Brick, and executes the TakeDamage function of that Brick
I figured it out. I clearly don't use Linq enough to have debugged this
Find on an empty List
you're trying to invoke the result, which is just null.
which is only happening because bricks is set up in awake, which could only be correct under the specific engineered circumstances you had earlier
while I included using Linq, it doesn't seem like it's being used in the script at all, from what my IDE tells me.
I'm only calling the list from OnCollisionExit, which won't happen for a while after starting the game?
as Prakkus said, you should really try to engineer your logic so that it all flows in one direction. You have a lot of initialisation scattered over the place in very similar methods that may or may not execute before or after each other. It's an easy way to create situations where one issue flows onto another and another as moving one point of failure just hits another
Yes, this was the only error (in OnCollisionExit2D) that was occuring after I fixed the startup ones.
Ironically I was starting to* do just that, and was improving, I thought.
But I see I do need a better approach.
I'm reading through everything that's been said. Need some time to catch up.
Thanks for all the help.
This is correct. From our perspective, it didn't make sense that the parent would be null, since it was a prefab and the parent was active.
I'll post a full report once I'm done working through this.
I have found the error in my own head
I was not aware that each object would run both Awake and OnEnable, before the next object's Awake
Assumed all Awake were run before any OnEnable.
Thanks a lot to everyone for helping out.
And credit to the friend who gave me the last bit of insight.
I will pay recompense by watching programming pattern tutorials
Have a nice day guys o/