どういうこと?
以下のコードを見てください。
PlayerPrefs.DeleteAll();
const string key = "KeyOfTheTwilight";
var value = PlayerPrefs.GetString(key, null);
Debug.Log("key:" + PlayerPrefs.HasKey(key));
Debug.Log("value:" + value);
Debug.Log("length:" + value.Length);
予想
PlayerPrefsは設定とかを保存しておくクラスです。
DeleteAll()はその名の通り保存された設定値すべてが消えます。
公式ドキュメントにはこうあります。
PlayerPrefs.GetString
キーが存在する場合、key に対応する値を取得します。
キーが存在しない場合、defaultValue を返します。
つまりこの場合はvalue
はdefaultValueであるnull
であり、value.Length
で長さを取得しようとしたところでご存知NullReferenceException
が出てしまう……はずです。
と思うじゃん?

value = null;
Debug.Log("length:" + value.Length);

キーが存在しないからdefaultValueが返るはず。
defaultValueはnull
。
null
ならNullReferenceException
が出るはず。
つまりdefaultValueをnullに設定したにもかかわらず空文字が返ってきている。
!!!!結!!!論!!!!
キーが存在する場合、key に対応する値を取得します。
キーが存在しない場合、defaultValue を返します。
キーが!!!!!!存在しない!!!!!!場合!!!!defaultValueを!!!!!!!返します!!?!!??!!?!うそつき!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
実験と推論
実験
実験1:int, floatなどstringではない型として保存した値を取得
PlayerPrefs.SetInt(key, 193);
PlayerPrefs.Save();
var value = PlayerPrefs.GetString(key, null);
実験2:nullを保存
PlayerPrefs.SetString(key, null);
PlayerPrefs.Save();
var value = PlayerPrefs.GetString(key, null);
実験1、2ともに空文字が返ってきます。
推論
PlayerPrefs.csは各Platformに深く依存しているクラスなので中身を見ることはできませんが、c#層の実装を見ることで原因を推測することはできます。
/// <summary>
/// <para>Returns the value corresponding to key in the preference file if it exists.</para>
/// </summary>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern string GetString(string key, string defaultValue);
/// <summary>
/// <para>Returns the value corresponding to key in the preference file if it exists.</para>
/// </summary>
/// <param name="key"></param>
/// <param name="defaultValue"></param>
public static string GetString(string key)
{
return PlayerPrefs.GetString(key, "");
}
推測ですが……本当に根拠もなにもない推測なんですが、PlayerPrefsの考える「値がないstring」は""
であってnull
ではない……?
ほんとうの結論
string.IsNullOrEmpty()
使おう!
PlayerPrefsにJSONを保存してMiniJSONでデシリアライズして……とやってる最中にこれが起きたため、要因を他に求めてドハマリしました。
なにげにUnityEditorはいったん終了させてもPlayerPrefsは保存されたままとか知らなかった……。
UnityEditor / unity 2018.3.0
上の環境でしか確認していないですが、UnityのバージョンとかPlatformによって動作が違ったらもっとムカつくので確認はしていません。
おしまい。