My fix to a tiny bug if you kill the target without the quest

I noticed that if I kill the target npc without taking the quest, then there will be a null reference error and the target will not “die”. Their mover will be disabled, but they will still whack at you if you get in attack range.

In my game, I would like npcs to exist (or in this case unexist) independent of the player’s quests, so I made one tiny update by adding a check for HasQuest() to CompletedObjective():

public void CompleteObjective(Quest quest, string objective)
        {
            if (!HasQuest(quest)) return;
            QuestStatus status = GetQuestStatus(quest);

            status.CompleteObjective(objective);

            if (status.IsComplete())
            {
                GiveReward(quest);
            }
            if (onUpdate != null)
            {
                onUpdate();
            }
        }

This way, you can still fight and kill a quest target without taking the quest. This could be helpful in situations were you would need to kill an NPC but may have missed the quest when you were back in town.

Curious if anyone else ran into this bug, and how they solved it?

At the top of your method, add a null check and you should no longer get the null reference error:

if (quest == null) return;

As for the rest of what you want to accomplish, I’d have to see the code to have a chance to make further suggestions.

This looks like the best solution.

That was the original fix that I tried, but for some reason it still gives me the error?

        public void CompleteObjective(Quest quest, string objective)
        {
            if (quest == null) return;
            QuestStatus status = GetQuestStatus(quest);

            status.CompleteObjective(objective);

            if (status.IsComplete())
            {
                GiveReward(quest);
            }
            if (onUpdate != null)
            {
                onUpdate();
            }
        }


NullReferenceException: Object reference not set to an instance of an object
Tribes.Quests.QuestList.CompleteObjective (Tribes.Quests.Quest quest, System.String objective) (at Assets/Scripts/Quests/QuestList.cs:38)
Tribes.Quests.QuestCompletion.CompleteObjective () (at Assets/Scripts/Quests/QuestCompletion.cs:16)
UnityEngine.Events.InvokableCall.Invoke () (at <49f4e7e791cc4fffacd88f729e2b1e4c>:0)
UnityEngine.Events.UnityEvent.Invoke () (at <49f4e7e791cc4fffacd88f729e2b1e4c>:0)
Tribes.Attributes.Health.TakeDamage (UnityEngine.GameObject instigator, System.Single damage) (at Assets/Scripts/Attributes/Health.cs:60)
Tribes.Combat.Fighter.Hit () (at Assets/Scripts/Combat/Fighter.cs:194)

line 38 is referring to status.CompleteObjective(objective); If there is no quest there should be no objectives either.

I’ll have to rewatch the video, I must have messed up along the way.

You just have to sit back and read the error and it tells you what you should be looking at to fix. At the one you’ve highlighted, it looks like it’s the other object (string) you’re feeding into the method that’s causing your null issue. Add:

if (objective == null) return;

        public void CompleteObjective(Quest quest, string objective)
        {
            Debug.Log("quest: " + quest + "objective: " + objective + "quest status: " + GetQuestStatus(quest));
            if (quest == null) return;
            if (objective == null) return;
            QuestStatus status = GetQuestStatus(quest);
            status.CompleteObjective(objective);

            if (status.IsComplete())
            {
                GiveReward(quest);
            }
            if (onUpdate != null)
            {
                onUpdate();
            }
        }

I am checking for both quest and objective, but I’m still getting the same null reference. The debug log prints the below:


It looks like the quests and objectives don’t return null, because they are populated in the quest completion component:

if i were to instead check for status == null, then it does work:


        public void CompleteObjective(Quest quest, string objective)
        {
            QuestStatus status = GetQuestStatus(quest);
            if (status == null) return;
            status.CompleteObjective(objective);

            if (status.IsComplete())
            {
                GiveReward(quest);
            }
            if (onUpdate != null)
            {
                onUpdate();
            }
        }
1 Like

That’s correct, it’s something that should have been in the original code. Sometimes, we leave out some of the null checking and other sanity checks in the code when presenting the code.

As a rule of thumb, I always recommend null checking whenever there is a possiblity that a reference can be null. This applies to all [SerializeField] references, all GetComponent references, etc.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms