1

I'm writing scripts for Unity3D in C# and have a little helper method in one of my classes called constraintForType that returns a public field for a certain type like so:

public Constraint topConstraint = Constraint.falseConstraint;
public Constraint bottomConstraint = Constraint.falseConstraint;

enum ConstraintType {
    Top,
    Bottom
}

Constraint constraintForType(ConstraintType type) {
    switch(type) {
    case ConstraintType.Top:
        return topConstraint;
    case ConstraintType.Bottom:
        return bottomConstraint;
    }

    return Constraint.falseConstraint;
}

I'm calling this method from the Update loop but it seems that the constraint that I'm returning is not the same as the public declaration (maybe a copy?).

So in the Update loop this would work:

void Update() {

    topConstraint.constant = // Calculated value
}

But this doesn't:

void Update() {

    Constraint con = constraintForType(ConstraintType.Top);
    con.constant = // Calculated value
}

I thought maybe the method was returning a copy of the public field so I changed it to:

void constraintForType(ConstraintType type, ref Constraint con) {

    switch(type) {
    case ConstraintType.Top:
        con = topConstraint;
        break;
    case ConstraintType.Bottom:
        con = bottomConstraint;
        break;
    }
}

So I then call this in the Update:

Constraint con = Constraint.falseConstraint;
constraintForType(ConstraintType.Top, ref con);

This still doesn't work though.

What is going on here?

EDIT:

Constraint is a struct.

Rob Sanders
  • 5,197
  • 3
  • 31
  • 58

2 Answers2

1

Change your Constraint -struct to class. Structs are value types that are (usually) immutable.

Simo Erkinheimo
  • 1,347
  • 9
  • 17
1

You are right, your first method is returning a copy of the stuct. However, your second version is making a copy as well:

void constraintForType(ConstraintType type, ref Constraint con) {

    switch(type) {
    case ConstraintType.Top:
        con = topConstraint; // struct is copied here
        break;
    case ConstraintType.Bottom:
        con = bottomConstraint; // struct is copied here
        break;
    }
}

One way to make this work in your case would be to assign inside the helper function

void constraintForType(ConstraintType type, Foo constant) {

    switch(type) {
    case ConstraintType.Top:
        topConstraint.constant = constant; 
        break;
    case ConstraintType.Bottom:
        bottomConstraint.constant = constant; 
        break;
    }
}

Of course, if you do not have a particular reason to use a mutable struct, use a class instead. Mutable structs have some difficulties.

Community
  • 1
  • 1
HugoRune
  • 13,157
  • 7
  • 69
  • 144