渋谷ほととぎす通信

「Unityをわかりやすく」初心者のためのゲーム作りブログ

構造体プロパティで起きるUnityトラブルと解決方法

構造体プロパティで起きるUnityトラブルと解決方法

こんにちは、Unityエンジニアのオオバです。

error CS1612: Cannot modify a value type return value of
こんなエラーに出会ったことはありませんか?

そう以下のソースで再現できます。

class Hoge  
{
    public Sample Direction { get; private set; }  
    // ポイントはココ!!  
    void Foo () => Direction.y = 0;  

    public struct Sample  
    {
        public int y;  
    }
}

このようにプロパティ定義した構造体Sample型
変数Directionの変数に値を代入すると以下のエラーです。

error CS1612: Cannot modify a value type return value of `Hoge.Direction'.  
Consider storing the value in a temporary variable  

プロパティ定を義した型(今回の場合Sample型)で代入しないといけません。

Unityを使っててよく出てくるのは、このようなコード。

void Bar ()  
{
    transform.localPosition.x = 10f;  
}

localPositionはプロパティなので同様のエラーが出力されます。
Vector3型を直接代入しないといけません。

👉 【Unityの基本】Transformを徹底解説「移動」や「回転」だけじゃない

正しくはコチラ

class Hoge  
{
    public Sample Direction{get; private set;}  

    void Foo () => Direction = new Sample {y = 0};  

    public struct Sample  
    {
        public int y;  
    }
}

Directionプロパティに対して、
構造体Sampleをセットするのが正しいやり方です。

構造体にすべきか、クラスにすべきか

構造体にすべきか、クラスにすべきか悩むケースがあります。
Microsoft公式にはこのようにあります。

プリミティブ型のような単一の値を論理的に表す (int, 、double, などです。)。
・16 バイト未満のサイズのインスタンスがあります。
・変更可能なことはできません。
・頻繁にボックス化することはありません。

クラスまたは構造体の選択 - Framework Design Guidelines | Microsoft Docsより

構造体は容量の少ないスタックメモリに積まれます。
値型であるためアクセスする度にメモリ内にコピーされます。
構造体内の変数が多ければ多いほどメモリコピー負荷が上がるということです。

要するに構造体の容量を小さくする必要があります。

ヒープメモリではなくスタックメモリに積まれるため、
ガベージコレクション(以下:GC)対象ではありません。
※GCはアプリケーションに大きな負荷がかかりFPSを大きく下げる場合があり

  • 寿命が少ない
  • 容量が小さい
  • 個数も少ない

上の条件を満たしているのであれば、
クラスではなく構造体を選択するメリットは十分にあ理想です。

ちなみにオオバの開発経験では構造体を選択することはあまりありませんでした。
クラスを必要な数だけ生成し、それらを使い回す方ケースの方が多いです。

「Unity初心者大学」というUnity初心者向けのYouTube始めました!!
ぜひチャンネル登録をお願いします!

最後まで読んでいただきありがとうございました!
すばらしいUnityライフをお過ごしください。

オススメ記事
検証環境
  • Unity5.4.2f1