質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

2625閲覧

UnityのJSON書き込みで実機にてエラーが起こる

momiji0210

総合スコア60

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/04/06 02:10

JsonUtilityを使い、JSONデータに直接書き込みを行いたいです。
エディター上では読み書きともに問題なく動作しています。

iPhoneとAndroidの実機だとエラーがでて書き込みができません。

こちらアクセス権限が問題な気がするのですが、直接書き込みをしたい場合どのようにすればよいのでしょうか。

StreamingAssetを使っており、JSONファイルはコチラに格納されています。

● iPhoneエラー内容
タップした時点でクラッシュ

● Androidエラー内容 クラッシュはしないが何も起こらない
UnauthorizedAccessException: Access to the path "/test.json" is denied.
at System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) [0x001b7] in <31c751c7f24e441c95072fa1e96928f2>:0

GameManager

1using System; 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.UI; 6using UnityEngine.SceneManagement; 7 8public class GameManager : MonoBehaviour { 9 10 JSON_TEST jsonTest = new JSON_TEST(); 11 12 // Start is called before the first frame update 13 void Start() { 14 15 // Jsonの読み込み 16 jsonTest.SetStreamingAssetsPath(); 17 jsonTest.SetFileName("test.json"); 18 jsonTest.Load(); 19 20 for(int i=0; i<jsonTest.list.Count; i++){ 21 Debug.Log(jsonTest.list[i].openFlag + " " + jsonTest.list[i].name); 22 } 23 24 } 25 26 // Update is called once per frame 27 void Update() { 28 29 if (Input.GetButton("Fire1")) { 30 jsonTest.list[1].openFlag = true; 31 jsonTest.Save(); 32 33 for(int i=0; i<jsonTest.list.Count; i++){ 34 Debug.Log(jsonTest.list[i].openFlag + " " + jsonTest.list[i].name); 35 } 36 } 37 } 38} 39

JsonManager

1using System; 2using System.IO; 3using System.Collections; 4using System.Collections.Generic; 5using UnityEngine; 6 7[Serializable] 8public class JSON_TEST : JSON_PARENT{ 9 10 [Serializable] 11 public class TEST { 12 13 public bool openFlag; 14 public string name; 15 public Color color; 16 17 // 初期化 18 public TEST(){ 19 20 } 21 22 // 初期化 23 public TEST(bool openFlag, string name, Color color){ 24 this.openFlag = openFlag; 25 this.name = name; 26 this.color = color; 27 } 28 29 }; 30 31 public List<TEST> list = new List<TEST>(); 32 33} 34 35public class JSON_PARENT { 36 37 [NonSerialized] 38 public string filePath = ""; 39 40 [NonSerialized] 41 public string fileName = ""; 42 43 // 読み込み 44 public void Load(){ 45 46 string fp = filePath + "/" + fileName; 47 48 #if UNITY_ANDROID && !UNITY_EDITOR 49 string textJson = GetStringAndroidStreamingAssets(fileName); 50 JsonUtility.FromJsonOverwrite (textJson, this); 51 #else 52 if(File.Exists(fp)){ 53 string textJson = File.ReadAllText (fp); 54 JsonUtility.FromJsonOverwrite (textJson, this); 55 }else{ 56 string textJson = JsonUtility.ToJson(new JSON_PARENT ()); 57 JsonUtility.FromJsonOverwrite (textJson, this); 58 } 59 #endif 60 61 } 62 63 // 保存 64 public void Save(){ 65 string textJson = JsonUtility.ToJson(this, true); 66 //Debug.Log(textJson); 67 68 string filePath = this.filePath + "/" + fileName; 69 70 // ファイルパスがない場合はディレクトリを生成 71 string directory = Path.GetDirectoryName(filePath); 72 if (!Directory.Exists(directory)){ 73 Directory.CreateDirectory(directory); 74 Debug.Log("CreateDirectory " + directory); 75 } 76 77 File.WriteAllText (filePath, textJson); 78 } 79 80 // rootPathの設定 (問題作成時用) 81 public void SetRootPath(){ 82 filePath = Application.dataPath + "/"; 83 } 84 85 // rootPathの設定 (問題作成時用) 86 public void SetRootDirectory(string path){ 87 filePath = path; 88 } 89 90 // StreamingAssetsPathの設定 (問題作成時用) 91 public void SetStreamingAssetsPath(){ 92 93 #if UNITY_EDITOR 94 filePath = Application.dataPath + "/StreamingAssets/"; 95 96 #elif UNITY_IOS 97 filePath = Application.dataPath + "/Raw/"; 98// 99 #elif UNITY_ANDROID 100 //filePath = "jar:file://" + Application.dataPath + "!/assets" + "/"; 101 //WWW www = new WWW(path); 102 //while (!www.isDone) {} 103 //return www.text; 104 105 #else 106 filePath = Application.dataPath + "/StreamingAssets/"; 107 #endif 108 109 } 110 111 // Androidの場合、StreamingAssetのファイル名から文字列を返す 112 public string GetStringAndroidStreamingAssets(string fileName){ 113 114 // Androidの場合 115 #if UNITY_ANDROID 116 string path = "jar:file://" + Application.dataPath + "!/assets" + "/" + fileName; 117 WWW www = new WWW(path); 118 while (!www.isDone) {} 119 return www.text; 120 121 #else 122 Debug.Log("not android"); 123 return ""; 124 #endif 125 } 126 127 // Pathの追加 128 public void AddPath(string path){ 129 filePath += path; 130 } 131 132 // ファイル名の設定 133 public void SetFileName(string fileName){ 134 this.fileName = fileName; 135 } 136 137 public void LogPath(){ 138 string fp = filePath + fileName; 139 Debug.Log(fp); 140 } 141}

json

1// StreamingAsset > test.json 2{ 3 "list": [ 4 { 5 "openFlag": false, 6 "name": "black", 7 "color": { 8 "r": 0.0, 9 "g": 0.0, 10 "b": 0.0, 11 "a": 1.0 12 } 13 }, 14 { 15 "openFlag": false, 16 "name": "white", 17 "color": { 18 "r": 1.0, 19 "g": 1.0, 20 "b": 1.0, 21 "a": 1.0 22 } 23 }, 24 { 25 "openFlag": false, 26 "name": "cyan", 27 "color": { 28 "r": 0.0, 29 "g": 1.0, 30 "b": 1.0, 31 "a": 1.0 32 } 33 }, 34 { 35 "openFlag": false, 36 "name": "yellow", 37 "color": { 38 "r": 1.0, 39 "g": 1.0, 40 "b": 0.0, 41 "a": 1.0 42 } 43 }, 44 { 45 "openFlag": false, 46 "name": "magenta", 47 "color": { 48 "r": 1.0, 49 "g": 0.0, 50 "b": 1.0, 51 "a": 1.0 52 } 53 } 54 ] 55} 56

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

そもそもStreamingAssetsにファイルを書き込むことは基本的にできません(Windowsやエディタは例外)。
そのため、書き込むときはApplication.persistentDataPath(一時的なものであればApplication.temporaryCachePathでも可)に書き込むようにしてください。


また、質問とは関係ないものもありますが、気になった点があります。

1点目として、StreamingAssetsはApplication.streamingAssetsPathで取得できます。
そのため、SetStreamingAssetsPath()は以下で済みます。

C#

1 public void SetStreamingAssetsPath(){ 2 filePath = Application.streamingAssetsPath + "/"; 3 }

2点目として、WWWクラスの受信を待つ際は、コルーチンの中で行ってください。
現状だとwhile (!www.isDone) {}で待機させているようですが、こうすると受信の完了までフリーズしてしまうので、避けるべきです。
そもそも、WWWクラス自体、古くて非推奨になっているので、書き換えるついでにUnityWebRequestに移行することをおすすめします。

投稿2020/04/06 03:46

fiveHundred

総合スコア10152

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

momiji0210

2020/04/06 05:18

詳細なご回答ありがとうございます。書き込みが元々できなかったのですね。 諸々わかりやすくありがとうございます。 while (!www.isDone) {}をしている理由ですが、ステージのマップデータなどがあり、 ゲーム開始時にそちらのデータをもとにオブジェクトを生成しております。 こちらで待機させないと、シーン開始時のStartでうまく動作しないことがございまして・・・。 こういった場合は、どのように読み込みが完了しているか判断すればよいのでしょうか。
fiveHundred

2020/04/06 06:05

読み込みが完了したかどうかのフラグ変数を用意し、その変数が変わったら処理を行う、という方法があります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問