Have A Class Find Itself In A List

I’m trying to have an object (of type Car) find the preceding car in a list. All of the Cars in the scene are added to the list so it will be in the list. I’ve tried using the FindIndex method, passing it “this” as an argument, but I get an error. Its refers to System.Predicate and I’ve never heard of or used it. Maybe I’m just going about this the wrong way, is there a simple method that I’ve passed up or does someone just need to teach me how to give the method a Predicate? Here’s my code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Car : MonoBehaviour
{
    //Public Variables

    //Private Variables
    private LevelData levelData;
    private List<Car> cars = new List<Car>();
    private Transform target;
    private int index;

    void Start ()
    {
        levelData = GameObject.FindGameObjectWithTag("Manager").GetComponent<LevelData>();
    }

    void Update ()
    {
        index = cars.FindIndex(this);
        if(index - 1 > -1)
            target = cars.FindIndex[index - 1].transform;
        else
            target = levelData.followMouse.transform;
    }
}

And then here’s the errors:

Assets/Code/Scripts/Cars/Car.cs(22,30): error CS1502: The best overloaded method match for `System.Collections.Generic.List.FindIndex(System.Predicate)’ has some invalid arguments

Assets/Code/Scripts/Cars/Car.cs(22,30): error CS1503: Argument #1' cannot convert Car’ expression to type `System.Predicate’

Assets/Code/Scripts/Cars/Car.cs(24,39): error CS0021: Cannot apply indexing with [ ] to an expression of type `method group’

MSDN implies you need a Predicate. Which is what the errors you get are saying. Also, your error on line 24 suggests that you have copied FindIndex where you don’t need it. Finally, shouldn’t cars be a static?

1 Like

Use IndexOf instead of FindIndex if you do no requires special comparison logic.

1 Like

Yeah I see that I need a predicate. I tried reading MSDNs documentation on it but was confused. I’ve never heard of a predicate. Could you give a brief and simple explanation of what it is and how I should use it in this context? As to cars being static, why should they be? Is there a benefit that I’m missing?

I’m assuming you’re saying it should be static because then can access it more easily. That was stupid of me not to do that, however, when I do make it static does the class that it is contained in also need to be static, because I got this error:

Static member `LevelData.cars’ cannot be accessed with an instance reference, qualify it with a type name instead

I originally wanted to make the LevelData class static so that all of the other classes would have to find it in their Start/Awake methods but then I couldn’t have it be of type Monobehaviour so I decided to let it be. Here’s my current code:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Car : MonoBehaviour
{
    //Public Variables

    //Private Variables
    private LevelData levelData;
    private Transform target;
    private int index;

    void Start ()
    {
        levelData = GameObject.FindGameObjectWithTag("Manager").GetComponent<LevelData>();
    }

    void Update ()
    {
        index = levelData.cars.IndexOf(this);
        if(index - 1 > -1)
            target = levelData.cars[index - 1].transform;
        else
            target = levelData.followMouse.transform;
    }
}

Use LevelData.cars if the list is to be static

I converted the whole class to be static, which was most of the problem, so pretty much everything is working now. 'm on my way to find another simple but unsolvable problem right now! Thanks guys.

A predicate is basically a true/false statement about an object. For example, “Find all dogs that are brown” or more formally “Find every dog x where x is brown”, the predicate is “x is brown”. In C# you’d write it like:

dogs.FindIndex(x => x.color == brown)

or to do what you were specifically looking for:

index = cars.FindIndex(x => x == this)

But like others said, IndexOf is simpler. Also like BoredMormon said, you need to capitalize LevelData in line 22 there. When accessing a static, you use the name of the class rather than the name of a variable; that’s what the error is telling you. You don’t need to make the entire class static. In fact you almost definitely do not want to make your “Car” class static because that means every car will have the same position and index.

1 Like

Thanks. This was helpful. Could you explain what the “=>” and “<=” stands for. Is it similar to “==” in the way that its a statement for you to check. Like how you can check if x is equal to x. == isn’t setting something equal to something else. I don’t really know the word for what it’s doing, but is the “=>” similar in functionality?

Comparison operators

== Is LHS equal to RHS
<= Is LHS less than or equal to RHS

= Is LHS greater then of equal to RHS

Assignment operator

= Assign RHS to LHS

Lambda operator

=> Uses the LHS as arguments to do the RHS in an unnamed method.

Confused? It helps to think of the => as an arrow. Something like goes to. The developers of C# really did us no favours when they defined => and >= to do two completely separate, unrelated tasks.

No, the “=>” is supposed to look like an arrow pointing to the right, and it’s used to make a “lambda statement”. Not to be confused with the similar looking “<=” which is “less than or equal to”. A lambda is like a mini-function, you put the parameters on the left and the function on the right. So this:

 x => x < 7

is basically the same as this:

bool MyFunction(int x) { return x < 7; }

Here’s the docs: http://msdn.microsoft.com/en-us/library/bb397687.aspx

Ok so continuing your 1st example I could say

int x = 6;
bool blah = x => x < 7;
//blah would equal true

Because its like a mini function returning whether or not the the following statement is true by feeding it the value that precedes the lambda. Right?

Not exactly… in this case “blah” is being set to the actual lambda function, and the “x” in the lambda isn’t related at all to the other x. You could do this:

int x = 6;
var foo = (y => y < 7);
bool blah = foo(x);

And then blah would be true. It’s a bit complicated; I recommend reading that help page I linked. I guess lambdas are also considered kind of advanced; you can get by without ever using them in C# if you really wanted to, but they’re useful once you figure them out, especially if you end up using LINQ at some point.

I recommended static because:

a) assuming you have 10 cars in the list, you only need one list.
b) If each of the 10 cars have their own list, how does car 3 add itself to 9 other lists?

I don’t think the class needs to be static, since that would mean you only have one object.

If you need to find things that are immediately previous or following in a list it may be worth looking into linked lists if you don’t need to do a lot of modification to the contents of the list. A regular list works a lot like an array but within a doubly linked list you basically have a bunch of objects (called “nodes”) that contain a link to the object after it and the object before it. That gives you a very easy way for one of the nodes to look at a node immediately before or after it with relative ease. C# has a built-in type but they’re also rather easy to program yourself.

I think using a linked list for those situations that you need to reference preceding or following objects would make your life much easier in this case.

Thanks for the advice. The linked list sounds like just what I need.