How Do I Apply A FlyWeight Design Pattern to Unity?

So I’ve been setting up this test to implement the flyweight pattern. It’s where I create an object class and a factory to basically spawn the same kind of object with different properties, in this case, color, size, and shape. So I have a dropdown menu for each property and a button to create the object. I want to use the getobject function in the factory class to create the object, but I can’t seem to create it right. I got the shape, but not the color or size. It has something to do with the parameters I set up for the function. I don’t want to just do what I’m doing right now to spawn cubes and cylinders. That’s just a test. If anyone could come up with a way around this, I appreciate it thank you.

public class FlyWeight : MonoBehaviour
{


    public static Button CreateButton;

    public static Color[] ColorList = { Color.red, Color.blue, Color.green };
    public static Vector3[] sizeList = {
        new Vector3 { x = 1, y = 1, z = 1 },
        new Vector3 { x = 2, y = 2, z = 2 },
        new Vector3 { x = 3, y = 3, z = 3 }
    };

    List<string> colors = new List<string>() { "Choose Color", "Red", "Blue", "Green" };
    List<string> shapes = new List<string>() { "Choose Shape", "Sphere", "Cube", "Cylinder" };
    List<string> sizes = new List<string>() { "Choose Size", "Small", "Medium", "Large" };

    public Dropdown Shapes;
    public Dropdown Colors;
    public Dropdown Sizes;

    private void Start()
    {
        Shapes.AddOptions(shapes);
        Colors.AddOptions(colors);
        Sizes.AddOptions(sizes);

    }

    public void TaskOnClick()
    {
        if (Shapes.value == 1)
        {
            Object sphere;
            Factory factory = new Factory();
            sphere = Factory.getObject();
            sphere.setColor(sphere, getColor());

        }
        else if (Shapes.value == 2)
        {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.GetComponent<Renderer>().material.color = getColor();
            cube.transform.localScale = getSize();

        }
        else if (Shapes.value == 3)
        {
            var cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
            cylinder.GetComponent<Renderer>().material.color = getColor();
            cylinder.transform.localScale = getSize();
 
        }
    }


    public Color getColor()
    {
        if (Colors.value == 1) { return  ColorList[0]; }
        else if (Colors.value == 2) { return ColorList[1]; }
        else if (Colors.value == 3) { return ColorList[2]; }
        else return Color.white;
    }

    public Vector3 getSize()
    {
        if (Sizes.value == 1)
        {
            return sizeList[0];
        }
        else if (Sizes.value == 2)
        {
            return sizeList[1];
        }
        else
        {
            return sizeList[2];
        }
    }
}

Object Class

public class Object
{
    private Color color;
    private Vector3 size;
    private int x, y;

    public Object ()
    {

    }

    public void setColor(Object o, Color c)
    {
        o.color = c;
    }
    public void setSize(Vector3 s)
    {
        this.size = s;
    }
    public void setX(int x) { this.x = x; }
    public void setY(int y) { this.y = y; }
}

Factory class

public class Factory
{
    private static List<Object> objects = new List<Object>();

    public static Object getObject()
    {
         Object obj = null;
       

        if (obj == null)
        {
            obj = new Object();
            objects.Add(obj);
        }
        return obj;
    }

}

There’s a handful of things to address, it is good you posted all the relevant code.

In “TaskOnClick” a Factory is instantiated, but the function being called is a static function, and not used. You can remove the “new Factory” there.

The name Object is slightly problematic, because it is often used, in various forms, as the base in a storage strategy, where Object refers to any class instantiation. Unity has one. Namespaces are used to separate such name collisions, but for such a classic name it is best to consider it a keyword used by Unity.

That said, in the Object class, setColor takes and Object as a parameter, but during this call, the instance is the same object. You should therefore change it to something like:

public void setColor( Color c )
{
 color = c;
}

You did that correctly for setSize (using this is a common pattern, though not necessary as I example above, that could have been this.color = c;

getColor can be simplified with something like:

public Color getColor()
{
 if ( Colors.value < 3 && Colors.value > 0 ) return ColorList[ Colors.value - 1 ];
 return Color.white;
}

Which is more important if the color list is larger.

At present an Object is only created for Shapes.value == 1 (Factory.getObject()) is only called there. Only the color is set, so that’s all that will be correct.

Nothing is calling setSize or setX/Y, so Objects don’t have anything set for them.

In TaskOnclick I can’t tell what you intend with cube and cylinder, and why no counterpart exists in sphere. These appear incomplete.

However, instead of using “if/elseif/elseif”, consider using a switch, something like:

 switch( Shapes.value )
         {
           case 1:    
            {
             Object sphere;
             Factory factory = new Factory();
             sphere = Factory.getObject();
             sphere.setColor(sphere, getColor());
            }
          break;

          case 2:
           {
             var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
             cube.GetComponent<Renderer>().material.color = getColor();
             cube.transform.localScale = getSize();
           }
          break;
      
         case 3:
         {
             var cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
             cylinder.GetComponent<Renderer>().material.color = getColor();
             cylinder.transform.localScale = getSize();
         }
        break;
      }// end of switch 

It may be advisable to consider passing the required parameters for a new object to Factory.getObject, and set the values in the factory, having the factory call (and thus initialize) setColor, setSize, etc.