Use Case: Curtains

Here we are going to use ObiCloth to set up some realistic, interactive curtains that you can open/close programatically.

Our curtains will be made of two cloth pieces, one at each side of the window. The first step is to create the geometry in any modelling program, I will use Blender. Make two sufficiently tesselated planes, making sure they are slightly wider than half of the window width, so that they overlap. This way, they will generate nice folds when closed instead of stretching out completely. Also, try to keep their topology as symmetric as possible, to avoid any simulation bias. Put both planes under a parent transform, your object hierarchy should look like this:



The most important detail to keep in mind when modelling the curtains is that the both planes should have their pivot point placed on one side, not in the center. This will allow the curtains to properly fold to the sides when they open. Also, align the curtains so that they lie flat in any of the 3 world planes (xz,xy or yz). Your geometry should resemble the following image:



Bring your geometry to Unity, and set up ObiCloth components for each curtain piece as usual. They should share a single ObiSolver component, which resides in the parent object of the curtains just to keep things nice and tidy.

Then fix all particles you wish the curtains to hang from, and click on "Generate tether constraints". Tether constraints will avoid over-stretching due to gravity, by linking all free particles to the ones we have fixed. Also, adjust the "Max bending" parameter to something between 0.02 and 0.04, and reduce the "Compression stiffness" to 0 if your curtains are made of very light fabric. These adjustments will allow the fabric to bend easily and create folds and wrinkles. You can also enable self-collisions and/or intercollisions, if you wish. Remember that the more constraints you use for your curtains, the more performance hungry they´ll get.



Hit play in the editor, and scale the curtain pieces along their horizontal axis (local y in my case, the green axis handle in the previous screenshot): you should see them open/close, because the only particles affected by scaling are the fixed ones. Now we will write a small script to control both at the same time using a single parameter, which will calculate the appropiate scale for us. Place this script on the curtain´s parent object:

    public class CurtainController : MonoBehaviour {

        [Range(0,1)]
        public float close = 0;

        public float openScale = 0.75f; //amount of scale applied when the curtains are fully open.
        public float closedScale = 0.3f;//amount of scale applied when the curtains are fully closed.

        private Transform left_curtain;
        private Transform right_curtain;

        void Awake () {
            left_curtain = gameObject.transform.GetChild(0);
            right_curtain = gameObject.transform.GetChild(1);
        }

        void Update () {

            float scale = Mathf.Lerp(openScale,closedScale,close);

            if (left_curtain != null)
                left_curtain.localScale = new Vector3(1,scale,1);
            if (right_curtain != null)
                right_curtain.localScale = new Vector3(1,scale,1);

        }
    }
                

Note that this script performs the scaling along local y axis, because my curtains lie flat on their local xz plane. You should modify the script to suit your particular geometry. You can open/close your curtains using the CurtainController's "close" parameter. If you want to, save the curtain´s parent object as a prefab and instantiate it any time you need some curtains :).

The result of our work.