- Home /
List.First not returning anything, while there is something
There is a weird bug in Unity, I think it's a bug at least, that doesn't let you find stuff in a List. My programming works perfectly outside of Unity, but when I run it in Unity again the code does not work and the List.First method returns null.. So, absolutely nothing.. I've asked this question on StackOverflow, but nobody seems to have a clue on how this works on the Unity Engine.
Once again: It works perfectly outside of the Unity Engine.
Some explanation:
I'm making something like an objective list with C#. I got it working and all, able to draw the objective list inside Unity, and make new objectives with them. I had an idea on how to delete something, I used System.Linq
and the List.First function to search for it. But it does not seem to work.
This is the 'Finishing and Creating Objectives' code.
public void NewObjective(string objectiveText, string objName)
{
objectives.Add(new Objective(objectiveText, objName)); //Add to the list Objective.
middleText("New Objective: " + objectiveText); //Display text on screen.
}
public void FinishObjective(string shortObj)
{
var value = objectives.First(x => x.ObjectiveName.Contains( shortObj ));
string completedTask = value.objectiveDescription;
middleText("Completed Objective: " + completedTask); //Display text on screen.
objectives.Remove(value); //Remove value. (Which doesn't find anything for some reason, so it can't delete anything from the list.)
}
And then in another class, I have it make a new objective, like this.
GameController.gameController
.GetComponent<GameController>()
.NewObjective("Foobar.", "foo"); //First is the Quest description,
and the second is the name for easy deletion.
(I've also included a objectiveID
method but I've omitted for ease. Oh, and if there's an alternative for having to type this long thing, please tell.)
In that same class, when the player completes something, I have this.
GameController.gameController
.GetComponent<GameController>()
.FinishObjective("foo"); //This has two possible methods,
the object ID (if defined) or the name of the objective.
Objectives is just easily defined as List objectives = new List(); inside the class.
This is the objectives class:
public class Objective : MonoBehaviour
{
public string objectiveDescription;
public string ObjectiveName;
public int ObjectiveID;
public Objective(string objective, string objectiveName)
{
objectiveDescription = objective;
ObjectiveName = objectiveName;
}
public Objective(string objective, string objectiveName, int objectiveID)
{
objectiveDescription = objective;
ObjectiveName = objectiveName;
ObjectiveID = objectiveID;
}
}
What is going on, what am I doing wrong and what can I do to fix this? If there's no alternative, what's another way of managing objectives? (Quests, Missions, whatever you'd like to call them.)
Thanks in advance!
Answer by Bunny83 · Apr 02, 2015 at 12:51 PM
Well, the problem is simple: You derived your Objective class from MonoBehaviour and created an instance with "new". That's not possible.
MonoBehaviours are Components and can only be "created" with AddComponent as they have to be attached to a GameObject. When you create one with the "new" keyword, the instance will be fake-null. Just remove the ": MonoBehaviour" from the Objective class and it works fine.
edit
ps: You shouldn't use "First" the way you did. First will throw an exception if the List is empty or if it can't find an element that satisfies your condition. First is always required to return a value. You might want to use "FirstOrDefault" instead which does the same as First but in the mentioned cases where it can't return a value it returns the default value for the given type (for all reference types that is "null").
Using FirstOrDefault requires you to do a null check afterwards since there's the possiblity that null is returned.
2. edit
About your question if you can write that line shorter:
GameController.gameController.GetComponent<GameController>().NewObjective("Foobar.", "foo");
Well it depends on how is "GameController.gameController" declared? I guess that should be some sort of singleton? If that's the case, you should declare the static gameController variable / property of type GameController so you don't have to use GetComponent all the time.
public class GameController : MonoBehaviour
{
public static GameController gameController;
void Awake()
{
gameController = this;
}
// [...]
}
If it's declared like this, you can simply do
GameController.gameController.NewObjective("Foobar.", "foo");
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
A node in a childnode? 1 Answer
Subtracting the position of transform from the position of Game Objects in a list. 1 Answer