Where to use Structs and classes?

Hey Guys! I’ve made a game which lags on some of the mobile devices. Recently, when I searched for optimisation tips in unity. I came across a UNITE CONFERENCE video on youtube. In this video they suggested that it is better to use structs instead of classes for preventing garbage collection.

I’ve a lot of scripts in my game and all of them are classes by default. I just want to know where can I use structs and classes.

EDITED : Suppose I’ve a gameObject with a script (ScriptA) attached to it. And if i’m making a reference to this gameObject via another script(ScriptB).

I this case should I use class or struct for ScriptA?

Thank you.

Hi,

Class is a reference type. If you create an object of that class, variable only holds a reference to memory. Structs on the other hand is a value type. If you create a struct, variable holds the actual value, not a reference to memory. Note that when the struct is assigned to a new variable, it is copied. Changes made to one copy do not affect the other copy.

You can use a struct if you dont need a reference variable. If you need a small data structure that holds a data that you wont modify later, structs are the best.

EDIT (as this is the main answer, I will add my view to this one):

The main difference between both is the way they are passed to methods.

public class MyClass
{
      public int valueA, valueB;
}
public class MyStruct
{
     public int valueA, valueB;
}

void MyMethod(MyClass myClassObject);
void MyMethod(MyStruct myStructObject);

When passing a class object, the compiler will copy the address value into the parameter which is stored on the method stack. Using the parameter then means to use the actual object as the compiler will jump to the given address location to modify valueA and valueB. Size of myClassObject is 4 bytes.

  myClassObject.valueA = 10;
  myClassObject->valueA = 10; // c++

The c++ way really indicates there is a movement to the value.

-

When passing the struct object, compiler will copy the entire structure content into a new struct object. It means now the stack is bigger than previous case. But it also means it is faster to access data since there is no jump in memory. The downside, you are not altering the original object, only the copy on the stack. You can use ref/out or return the modified copy value if the result is needed outside the method. Size of myStructObject is 2* sizeof(int) = 8 bytes (most likely more but in a nutshell to get the point).

-

This brings one major limitation for struct, they cannot inherit or be inherited. This is because when making a class hierarchy, it does not matter how deep and the content of it all, the compiler will make the parameter reference as 4 bytes or 8 bytes (depending on architecture). For a struct to be passed as parameter, the compiler needs to know how much space is needed on the stack to allocate since it will copy all content. Problem with generic type is that compiler is only discovering the object type at runtime, and it would be messy or technically dangerous to try and figure out the full tree of a struct. So the compiler will prevent it.

Here is my take on this. Please read it carefully as it might save you some headache if you are to use structs in the future.

  • If you will be creating lots of objects, you are advised to use a
    struct
    , it’s faster as it’s stored on
    the stack rather than on the heap.
  • If you need to check for null, use a
    class
    . Structs, as all value types
    can’t be null. Let’s take an example:

A function called GetValidTargetPosition shall return an object of type TargetPosition when the player clicks somewhere on a map. If the player clicks a non-reachable position GetValidTargetPosition function would return null.

As structs can’t be null, TargetPosition should be a class if you want to do something like

TargetPosition targetPosition = GetValidTargetPosition();
if (targetPosition!=null){
     MoveCharacterTo(targetPosition);
}
  • If you want to easily modify the data inside a method,
    use a class
    . When you call
    a method with a struct as a
    parameter a copy of it is created and being sent to the method.
    Modifying the struct’s values inside the method will
    have no effect outside of the method’s scope.

For your reference:

Structs can indeed be faster and easier on memory if you use them correctly. Basically, they should be used in cases where you don’t care about polymorphism and other class features. You’d normally use structs for smaller groups of common data, especially for use in arrays (as in an array of structs).

I recommend checking out this topic: Where to use struct in C#?. And here’s a performance comparison for correct and wrong use: C# performance – class vs struct.

This Class attached in Gameobject

   public class ClassAtachGameobject : MonoBehaviour {
    	struct myPoint{
    		int x;
    		int y;
    	}
    	public myPoint mp;
    
    }

Invoke from other class.

SomeGameObject.GetComponent<ClassAtachGameobject > ().mp.x=99;