transform.position.x等の値を変える方法

Unityは
`transform.position.x = 123f;`と書くと
エラーになるんですが
positionのxだけを変えるとなると

``` C#
transform.position = new Vector3(123f, transform.position.y, transform.position.z);
```

こんな長ったらしくなるので
`transform.position.x = 123f;`に近い書き方ができないかなと
ポケモンをしながら真剣に考えたら
一つの方法を思いついたので
共有したいと思います。

よく紹介されてる方法として

``` C#
public static class TransformExtensions
{
    public static void SetPositionX(this Transform self, float x)
    {
        self.position.x = x;
    }
}
```

というクラスを用意すると
`transform.SetPositionX(123f);`という風に書ける方法があります。
これでもいいんですが`transform.position.x += 123f;`のように
加算したいときは別にAddPositionXのような関数を書かなければいけないので
必要な関数の数が膨大になります。
ざっと挙げてみると

- SetPositionX
- SetPositionY
- SetPositionZ
- AddPositionX
- AddPositionY
- AddPositionZ
- SubPositionX
- SubPositionY
- SubPositionZ
- MulPositionX
- MulPositionY
- MulPositionZ
- DivPositionX
- DivPositionY
- DivPositionZ
- SetLocalPositionX
- SetLocalPositionY
- SetLocalPositionZ
- AddLocalPositionX
- AddLocalPositionY
- AddLocalPositionZ
- SubLocalPositionX
- SubLocalPositionY
- SubLocalPositionZ
- MulLocalPositionX
- MulLocalPositionY
- MulLocalPositionZ
- DivLocalPositionX
- DivLocalPositionY
- DivLocalPositionZ
- SetEulerAnglesX
- SetEulerAnglesY
- SetEulerAnglesZ
- AddEulerAnglesX
- AddEulerAnglesY
- AddEulerAnglesZ
- SubEulerAnglesX
- SubEulerAnglesY
- SubEulerAnglesZ
- MulEulerAnglesX
- MulEulerAnglesY
- MulEulerAnglesZ
- DivEulerAnglesX
- DivEulerAnglesY
- DivEulerAnglesZ
- SetLocalEulerAnglesX
- SetLocalEulerAnglesY
- SetLocalEulerAnglesZ
- AddLocalEulerAnglesX
- AddLocalEulerAnglesY
- AddLocalEulerAnglesZ
- SubLocalEulerAnglesX
- SubLocalEulerAnglesY
- SubLocalEulerAnglesZ
- MulLocalEulerAnglesX
- MulLocalEulerAnglesY
- MulLocalEulerAnglesZ
- DivLocalEulerAnglesX
- DivLocalEulerAnglesY
- DivLocalEulerAnglesZ
- SetLocalScaleX
- SetLocalScaleY
- SetLocalScaleZ
- AddLocalScaleX
- AddLocalScaleY
- AddLocalScaleZ
- SubLocalScaleX
- SubLocalScaleY
- SubLocalScaleZ
- MulLocalScaleX
- MulLocalScaleY
- MulLocalScaleZ
- DivLocalScaleX
- DivLocalScaleY
- DivLocalScaleZ

冗長ですよね。
でもこの記事の方法を使えば

``` C#
transform.SetPosition(t => t.x = 123f);
transform.SetPosition(t => t.x += 456f);
transform.SetPosition(t => {
    t.y *= 123f;
    t.z /= 456f;
});
```

という風に自由に値をいじれます。
わかる人にはわかると思いますが、ラムダ式を使います。
下のように書けば使えるようになります。

``` C#
using System;

public static class TransformExtensions
{
    public class WrappedVector3
    {
        public Vector3 vector3;

        public float x { get => vector3.x; set => vector3.x = value; }
        public float y { get => vector3.y; set => vector3.y = value; }
        public float z { get => vector3.z; set => vector3.z = value; }
    }

    public static void SetPosition(this Transform self, Action<WrappedVector3> setter)
    {
        WrappedVector3 temp = new WrappedVector3();
        temp.vector3 = self.position;
        setter(temp);
        self.position = temp.vector3;
    }

    public static void SetLocalPosition(this Transform self, Action<WrappedVector3> setter)
    {
        WrappedVector3 temp = new WrappedVector3();
        temp.vector3 = self.localPosition;
        setter(temp);
        self.localPosition = temp.vector3;
    }

    public static void SetEulerAngles(this Transform self, Action<WrappedVector3> setter)
    {
        WrappedVector3 temp = new WrappedVector3();
        temp.vector3 = self.eulerAngles;
        setter(temp);
        self.eulerAngles = temp.vector3;
    }

    public static void SetLocalEulerAngles(this Transform self, Action<WrappedVector3> setter)
    {
        WrappedVector3 temp = new WrappedVector3();
        temp.vector3 = self.localEulerAngles;
        setter(temp);
        self.localEulerAngles = temp.vector3;
    }

    public static void SetLocalScale(this Transform self, Action<WrappedVector3> setter)
    {
        WrappedVector3 temp = new WrappedVector3();
        temp.vector3 = self.localScale;
        setter(temp);
        self.localScale = temp.vector3;
    }
}
```

これで、positionもlocalPositionもeulerAnglesもlocalEulerAnglesもlocalScaleも
x、y、z、どの値も自由にいじることができます。

これが自分が考えうる限り
一番スマートだと思います。
もっといい方法があるならぜひ教えてください！