UnityEngine擬似コードから考える transform.position

2018年12月17日

transform.position.x = 5.0f
ひよこ先生

としたところ、エラーが発生して代入できない経験はありませんか?
その場合、

float posX = 5.0f;
float posY = transform.position.y;
float posZ = transform.position.z;
transform.position = new Vector3(posX, posY, posZ);
ひよこ先生

という書き方をすれば、大丈夫なのですが、なぜ?と思いますよね。
理解を深めるために簡単なコードとUnityEngineのシミュレーションコードから、
内部の動作を確認してみましょう。C#のコードから追ってみてください。

C#の確認コード

正常終了(フィールドへのアクセス)

using UnityEngine;

public class PositionSetSample : MonoBehaviour
{
    void Start()
    {
        MyPosition myPos = new MyPosition();

        // 直接フィールド値を変更します
        myPos.pos.x = 4;
    }
}

public class MyPosition
{
    public Vector3 pos;
}

public struct Vector3
{
    public int x;
}

エラー(プロパティへのアクセス)

using UnityEngine;

public class PositionSetSample : MonoBehaviour
{
    void Start()
    {
        MyPosition myPos = new MyPosition();

        // 値型のコピーが渡されるため、変更してもPosプロパティの値は変わらない
        myPos.Pos.x = 4;

        // 次のコードと同じです。元のプロパティは変更されません
        Vector3 temp = myPos.Pos;
        temp.x = 4;
    }
}

public class MyPosition
{
    private Vector3 pos;

    public Vector3 Pos
    {
        get
        {
            return pos;
        }

        set
        {
            pos = value;
        }
    }
}

public struct Vector3
{
    public int x;
}
ひよこ先生

さらに理解を深めるためにUnityEngineのシミュレーションコードから、
内部の動作を確認してみましょう。C#のコードから追ってみてください。

Unityエンジンのシミュレーションサンプル

using System;

namespace SimulationUnityEngine
{
    // 3次元ベクター情報の構造体
    public struct Vector3
    {
        // フィールド
        public float x;
        public float y;
        public float z;
 
        // コンストラクタ
        public Vector3(float x, float y, float z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
 
        // 静的プロパティ
        public static Vector3 forward
        {
            get
            {
                return new Vector3(0f, 0f, 1f);
            }
        }
 
        // 演算子オーバーロード
        public static Vector3 operator +(Vector3 a, Vector3 b)
        {
            return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
        }
    }
 
    // トランスフォーム情報のクラス
    public class Transform
    {
        private Vector3 internalPos;

        public Vector3 position
        {
            get
            {
                return internalPos;
            }
            set
            {
                internalPos = value;
            }
        }
    }
 
    class Program
    {
        static void Main(string[] args)
        {
            Transform transform = new Transform();
            float posX = transform.position.x;
            float posY = transform.position.y;
            float posZ = transform.position.z;

            Console.WriteLine($" position x = {posX}, y = {posY}, z = {posZ}”);
 
            // これはダメ。transform.position の設定値は、プロパティのため。
            // .xのfloat型までの代入はできない。
            // transform.position.x = posX;
 
            posX += 10.0f;
            posY += 3.0f;
            posZ += 5.0f;
            // これはOK。コンストラクタを使って代入をしているため。
            transform.position = new Vector3(posX, posY, posZ);
            Console.WriteLine($" position x = {posX}, y = {posY}, z = {posZ}");
        }
    }
}

/*
    // 実際のプログラムで x,y,z = (10,10,10)の地点にゲームオブジェクトがある設定。
    transform.position = new Vector3(10f, 10f, 10f);
    Console.WriteLine($" position x = {transform.position.x}, 
                                  y = {transform.position.y}, 
                                  z = {transform.position.z}”);
 
    // 一歩前に進む。
    // forwardプロパティは、staticなのでインスタンスを作る必要はない(newしない)
    // z軸の座標が+1される。つまり3Dオブジェクトの場合、前進することになる。   
    transform.position += Vector3.forward;
    Console.WriteLine($" position x = {transform.position.x}, 
                                  y = {transform.position.y}, 
                                  z = {transform.position.z}");
*/

表示

position x = 0, y = 0, z = 0
position x = 10, y = 3, z = 5
/*
position x = 10, y = 10, z = 10
position x = 10, y = 10, z = 11
*/

Unityのpositionは、値型のプロパティになります。次のリンクにあるように呼び出すとコピーされた値が返ってくるため、この値を変更しても実際のposition値は変更されません。

2018年12月17日C#,Unity

Posted by hidepon