ピックアップ記事
Unityでは動作していたのに実機で動作しなくなった場合に、確認すべき箇所

Unityでは動作していたのに実機で動作しなくなった場合に、確認すべき箇所

unityで問題なく動作していたゲームをビルドし、実機でテストを行なった場合に動作しなくなることがありました。

その際の原因となった箇所、対処法をメモ。

 

原因は、foreachで回す値にnullが含まれていることでした。

例えば、以下のようにnullを含む配列をforeachで回すような状況です。

public string[] items = {"item1", null , "item3"};
foreach (var item in items)
{
    Debug.Log(item);
}

 

解決方法1

対処法は、以下のような形です。

public string[] items = {"item1", null , "item3"};
foreach (var item in items ?? Enumerable.Empty<T>())
{
    Debug.Log(item);
}

 

??演算子は、null合体演算子とも呼び、null値である場合には、右側の値(Enumerable.Empty<T>())を返すようです。

??演算子参考:https://docs.microsoft.com/ja-jp/previous-versions/ms173224(v=vs.120)

参考:https://tiratom.hatenablog.com/entry/2018/12/16/foreach%E3%81%AE%E6%99%82%E3%81%AENullReferenceException%E3%82%92%E5%9B%9E%E9%81%BF%E3%81%99%E3%82%8B

 

また、この状態だと利用しづらいため、以下のように拡張メソッドを作成することが推奨されています。

public static IEnumerable<T> OrEmptyIfNull<T>(this IEnumerable<T> collection)
{
    return collection ?? Enumerable.Empty<T>();
}

 

利用方法としては、以下のような形です。

public string[] items = {"item1", null , "item3"};
foreach (var item in items.OrEmptyIfNull())
{
    Debug.Log(item);
}

 

もし、以下のようなエラーが出る場合には、using宣言が必要です。

The name 'Enumerable' does not exist in the current context [Assembly-CSharp]csharp(CS0103)
using System.Linq; 

 

解決法2

上記のような方法(解決法1)では、null値が入った場合に、その型のemptyを返すという処理でした。

しかし、nullを除去した配列を再生成する場合には、以下の方法が良さそうです。

 

public static IEnumerable<T> WhereNotNull<T>(this IEnumerable<T> source) 
    where T : class 
{
    if (source == null) 
    { 
        return Enumerable.Empty<T>(); 
    } 
    return source.Where(x => x != null);
}

参考:https://qiita.com/shima_/items/060fd3f35ea59ecd576a

 

私の場合は、配列数からアニメーションを生成していたため、nullを除去する必要があり、こちらの方法をとりました。

 

もし、null判定が正しく行えない場合には、以下の記事が参考になると思います。

おすすめの記事