Set one coordinate for every list element to 0

Hey folks,

a simple question for you, but hard to solve for me…

I have a Vector3 List with a few elements in it. I want to set the y-Coordinate of every element to 0, since I want to move only on the x- and z-Axis.

I tried to solve it by trying this:

foreach (Vector3 element in list)
{
element.y = 0;
}

but this does not work.

Can you help a coding-newbie and tell me what’s wrong with that?

Much thanks.

Nik

Try:

for (int i = 0 ; i < list.Count ; i++)
{
list[i] = new Vector3 (list[i].x, 0f, list[i].z;
}

Foreach elements when are readonly, because this ur changes don’t take effect. Use another way to iterate and all will be fine :stuck_out_tongue_winking_eye:

1 Like

A foreach loop is not readonly. The problem here is that Vector3 is a struct which means it is a copy you’re working with and not a reference.
In this case when working with structs you have to use a for loop so you can overwrite the list item’s value like @ItzChris92 suggested.

Yes, it is.
When u use a foreach in some container what you are doing is iterating over a “thing” that implements a version of IEnumerable and to access elements this container provides a Current property that has a get but not a set, which means that items are readonly. But let’s see some code

Let’s say that we an value and an ref kind of structure

public class RefObject
{
    public int field;

    public RefObject(int value)
    {
        this.field = value;
    }
}

public struct ValueObject
{
    public int field;

    public ValueObject(int value)
    {
        this.field = value;
    }
}

If u try to iterate and change fields with foreach with

static void Main(string[] args)
{
    var refList = new List<RefObject>{new RefObject(1), new RefObject(2), new RefObject(3)};
    var valueList = new List<ValueObject>{new ValueObject(1), new ValueObject(2), new ValueObject(3)};

    foreach (var item in refList)
    {
        item.field++;
    }

    // ERRO: does NOT compile
    // foreach (var item in valueList)
    // {
    //     item.field++;
    // }

    System.Console.WriteLine("Ref:");
    refList.ForEach(x => System.Console.Write($"{x.field}  "));

    System.Console.WriteLine();
    System.Console.WriteLine("Value:");
    valueList.ForEach(x => System.Console.Write($"{x.field}  "));
}

If u run above code, u’ll see that the first foreach really changed fields in ref type, this is because u are working with reference types, so u are never actually touching the container because all that container is storing is references to objects. If u try something like

item = new RefObject(0) *inside ur first foreach

u’ll get that same error that we have when working with structs, because now u are really chaging information (AKA: references) in the container. In a container of a value type (second foreach), the container really have all information contained in struct, so any change in an element will change the container info.

And only to finish, as @MaskedMouse said Vector3 is a struct

References:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/statements#the-foreach-statement

Yeah in that sense it is read only.
I was actually already assuming List where class would always be a container for the thing you’re trying to change. A referenced object rather than a Vector3 struct.

1 Like