参照型と値型

用語

transform.position

positionはTransformのプロパティです。型はstruct Vector3です。

次の操作の結果を考えてみてください。

  • Unityのプロジェクトを作成し、HierarchyでCubeとSphereを作成します。
  • ProjectでC#Scriptを2つ作りCubeとShpereというファイル名にします。
  • GameObjectのCubeにC#ScriptのCubeを、GameObjectのShpereにC#ScriptのShpereをアタッチします。
  • C#ScriptのCubeとSphereはそれぞれ以下のようにします。
using UnityEngine;
public class Cube : MonoBehaviour
{    
    void Start()
    {
        transform.position.Set(0, 1, 0);
    }
}
using UnityEngine;
public class Sphere : MonoBehaviour
{
    void Start()
    {
        transform.position = new Vector3(0, 1, 0);
    }
}

Play前はCubeとSphereは重なっています。Play後はどのようになるでしょうか?

ツールバーの真ん中にあるPlayボタンを押します。

正解は、Cubeの上にSphereがあります。

参照型と値型

C#ではclassは参照型ですが、structは値型です。値型はコピー先を変更してもコピー元には反映されません。

using UnityEngine;
struct S
{
    public int s;
}
class C
{
    public int c;
}
public class Cube : MonoBehaviour
{    
    void Start()
    {
        C c1 = new C();
        C c2 = c1; // 参照のコピー
        c2.c = 1; // c1.cは1、c2.cも1 同じ値を指している
        S s1 = new S();
        S s2 = s1; // 値のコピー
        s2.s = 1; // s1.sは0、s2.sは1 異なる値を持つ
        Debug.Log(c1.c); // 1
        Debug.Log(s1.s); // 0

        transform.position.Set(0, 1, 0);
    }
}

positionはプロパティです。型はstruct Vector3です。値型のgetterは返却時に値のコピーが発生します。

Vector3 position = transform.position; // 値のコピー
position.Set(0,1,0); // コピーした値を変更

コピーしたpositionを変更してもコピー元には反映されません。

Vector3 position = transform.position; // 値のコピー
position.Set(0,1,0); // コピーした値を変更
transform.position = position; // 変更した値を設定

変更したpositionを元のpositionにコピーすれば反映されます。

ref

void Start()
{
    Vector3 position = new Vector3(0,0,0);
    Move(ref position);
    Debug.Log(position); // (1.0,2.0,3.0)
}
void Move(ref Vector3 position)
{
    position.Set(1, 2, 3);        
}

値型はrefをつけることで参照として引数渡しができます。ただし、Move(ref transform.position);はプロパティのgetterで値のコピーが発生しているのでエラーになります。

メソッドは一つの値しか返せません。複数の値を返したいときにrefを使います。

コメント