1

I have a published game with Crashlytics, that run on Android and iOS.

I have records of "Object reference not set to an instance of an object" exceptions that tell me in which method a null reference has been encountered, but not exactly which reference, or on which line this happened.

The code runs successfully in local tests, but in real usage scenarios, null references can happen.

Please note in Unity, this can mean an actual MonoBehaviour object is destroyed and no more available, so adding null checks everywhere doesn't help. I want to know exactly which object has been destroyed, so I can find out the sequence of events that leads to the exception.

I've thought about adding Crashlytics.SetCustomKey() every few lines with an updated value so I can at least guess on which line this happens, so I can make better guesses.

But is there any better strategy you would suggest?

Edit: This question has been marked as duplicate, so I'm describing why it's not a duplicate of the mentioned questions.

I already know why a NullReferenceException happens, and if it happened locally for me, I could fix it. This question is a separate question from the mentioned duplicates. The question is about a complex situation when a sequence of events lead to some objects being destroyed, when they are not expected to be destroyed.

My question is more related to better utilizing Crashlytics, than related to NullReferenceException.

To describe the situation better, this is a boards game. For each round of game, there are some pieces created on board, and when player touches the boards, then some highlight objects are created on board, so player can select where he can move a piece.

As a possible example, when a player restarts the game, or leaves the game in any situation, those objects are destroyed.

But another job may finish it's job after the refresh (could be the AI thinking) and then expects objects on board, and they are not there anymore!

I really don't know what code to share, I think I'd need to share a big share of the project. And I don't think that helps too. Because I'm not looking for direct answers to the problem. But I'm generally asking about how to better get more info about NullReferenceExceptions recorded by Crashlytics.

I've also already searched, but found no solution for my specific problem.

So considering the situation described, I know the method in which the exception happens. How do you think I can know on which line this exception happens, or which object is null, when I have the record in Crashlytics? (Besides the solution I mentioned myself)

Edit 2: I initially thought the stacktrace might distract people form the actual problem, but looking at the comments, I think it actually helps.

This is the stacktrace:

Non-fatal Exception: java.lang.Exception: NullReferenceException : Object reference not set to an instance of an object. at OfflineGameScreen.MoveSuggestionTouched(OfflineGameScreen) at OfflineGameScreen+<MakeNextMoveByBot>d__74.MoveNext(OfflineGameScreen+<MakeNextMoveByBot>d__74) at System.Threading.ContextCallback.Invoke(System.Threading.ContextCallback) at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext) at System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner.Run(System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner) at System.Action.Invoke(System.Action) at System.Threading.SendOrPostCallback.Invoke(System.Threading.SendOrPostCallback) at UnityEngine.UnitySynchronizationContext+WorkRequest.Invoke(UnityEngine.UnitySynchronizationContext+WorkRequest) at UnityEngine.UnitySynchronizationContext.Exec(UnityEngine.UnitySynchronizationContext)

Paiman Roointan
  • 514
  • 5
  • 17
  • [GetInstanceID](https://docs.unity3d.com/ScriptReference/Object.GetInstanceID.html)? – rustyBucketBay Jul 25 '21 at 15:23
  • Could you add your code and the exact exception log? – derHugo Jul 25 '21 at 16:19
  • 1
    @PeterDuniho I don't think this should be closed too early .. I would assume OP knows exactly what a NullRef is and how you find it while debugging ... however, this question is about the Crashlytics logging system logging the exception in a **built application** where none of the given answers of the duplicates are really helpful – derHugo Jul 25 '21 at 17:29
  • If you get a `NullReferemceException` it can really be anything, a not initialized reference field/variable of any class/reference type .. if it was a Unity object you destroy it would be more likely to get a `MissingReferenceException` which would tell you something similar to `The reference of type XY you are trying to access was destroyed` or something like that. – derHugo Jul 25 '21 at 17:34
  • @derHugo exactly, I've updated the question to better describe the problem. Also, I only want to on which object reference this has happened, or at least on which line. Maybe considering the solution I talked about in the question can help better understand what I actually need. – Paiman Roointan Jul 25 '21 at 17:39
  • @derHugo: the process of diagnosis NRE is the same, regardless of how you find out about it. Frankly, _"is there any better strategy you would suggest?"_ is too broad anyway. There's a lot that keeps this question from being useful. But fundamentally, it's just that it's a straight-up duplicate of the canonical NRE Q&A. – Peter Duniho Jul 25 '21 at 17:45
  • @PeterDuniho it's obviously not the same. If you can reproduce it, you can attach the debugger, and fix the problem. For exceptions recorded live in production without a way to reproduce, you need to use different tools. Even if the process is similar, the tools used are different. – Paiman Roointan Jul 25 '21 at 17:54
  • @PaimanRoointan: the canonical NRE Q&A covers quite a lot of ground, much more than the _"attach the debugger"_ that you seem to think it's limited to. – Peter Duniho Jul 25 '21 at 17:55
  • The exception at least tell you exactly which method you have to look at .. could you post that method `OfflineGameScreen.MoveSuggestionTouched` code? – derHugo Jul 25 '21 at 18:00
  • @derHugo The code is big and complex, and I think there are lots of reliance on other codes. Besides, I'm looking for a general solution about Crashlytics to help in all similar situations. But If you think posting the code helps, I need to ask for permission and then can share it. – Paiman Roointan Jul 25 '21 at 18:09
  • I always put the general methods in a try-catch, so if an exception is created I send the user to an error page from which with a button he can send me all the data with which the method was started, so I reply the error. (bad practice? I'm not an expert) – Francesco - FL Jul 25 '21 at 18:59
  • @FreeLearning The exception is already catched. I just need to know on which line and for which object reference it happens. – Paiman Roointan Jul 25 '21 at 19:09

1 Answers1

1

Don't know the details if your code of course, but you may log the InstanceID of your object on destruction, and also before where the error is thrown. That might lead you to the logic gap where the exception might occur.

Be carefull with the nullchecks, mainly in the Updates() because they are not "free", as unity has it own implementation of the == operator on dealing with the typical if (myGameObject == null) {}.

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • 2
    I don't think the instance ID helps much here. The rest is a good advice though not even on how to avoid the exception in the first place and actually no answer at all to OPs question on how to find out where exactly it was thrown if an exception **is** thrown ;) – derHugo Jul 25 '21 at 16:22
  • Exactly .. then why answer? ;) – derHugo Jul 25 '21 at 16:24
  • thought that the instanceID might help the OP with the "How to find out which object reference is null" – rustyBucketBay Jul 25 '21 at 16:26
  • If the object is `null` then you won't be able to access its instance ID either ;) – derHugo Jul 25 '21 at 16:34
  • not for the case where I suggest to log the InstanceID of your object on destruction. Where I suggest "also before where the error is thrown" can be understood as to Debug.Log the instanceID where Its going to be helpfull to follow the execution flow so that can give you a broader view of what its happening to catch the bug. Its true that at the time the error occurs, the instance wont be available, but maybe the stack trace for that instance ID can be of help. – rustyBucketBay Jul 25 '21 at 17:17
  • 1
    I think in that case the object name etc would help much more .. however, OP isn't even sure if it is about a UnityEngine.Object at all .. it can as well be an uninitialized array or anything else since the general c# Nullreferenceexception is thrown and not one of the unity specific ones like `MissingReferenceException` which would be the usual exception for a destroyed object .. it would additionally actually tell you exactly that like `You are trying to access an object but is has been destroyed` or something similar ;) – derHugo Jul 25 '21 at 17:28
  • I'm adding the stacktrace to the question – Paiman Roointan Jul 25 '21 at 17:42
  • 1
    @rustyBucketBay Your answer helps in a way! I think I can null check every item that is accessed in the method (it's not a huge method), and log it if anything is null for Crashlytics. I didn't want to null check everything because it couldn't help fix the problem, but I can do it to log which object reference is null! Thanks, and Upvoted. – Paiman Roointan Jul 25 '21 at 17:52