大部分遊戲都會使用到「讀取」、「儲存」狀態與進度,本篇 「Unity 範例檔」示範如何使用Unity內建的 JsonUtility 進行 Json 檔案的讀存取。
JSON檔案的維基百科
P.S 話說JSON的ICON也太帥氣了 >////<
P.S 我在google上面打上『Unity Json 教學』,出來結果都是額外用 LitJSON 這個三年沒更新的插件了...那個沒有內建的速度快而且可能會有些問題...。2017.05.11
P.S 跟各位致歉,剛才發現我提供的教學檔是舊的,裡面並沒有套入Load部份 2017.05.11
有網友回覆說專案建置後Json檔案不會建置出來 @@
我上網查了一下... 改將 Json檔案放置到 Assets/StreamingAssets
就可以解決這問題~ 但是缺點是這檔案就是完全沒有被封裝起來,
因此使用者可以很簡單的就用文字編輯器改資料了' 2017.09.24
網友再度表示第二版的做法放在PC沒問題,但是輸出成APK就無法作用了!@@
Google 大神再度引領我找到解答: Application.persistentDataPath
使用persistenDataPath的範例檔案我放在下面2017.11.20版了。
[教學檔下載]
連結 2017.09.24 版本 (新版本) (2021.10.12更新連結)
[狀態存檔]
- 假設我們現在要存檔下面五項資料
- 玩家名稱,sammaru
- 玩家等級,87級
- 玩家所處座標,X:33,Y:0,Z:33
- 這三項資料的變數型態剛好都是不同變數類型:
string playerName; //玩家名稱,sammaru int level; //玩家等級,87級 vector3 postion; //玩家座標,vector3(0,0,500)
- 為了讓檔案JsonUtility可以讀存這些檔案,
我們需要建立一個class來承接資訊:public class playerState { public string name; public int level; public Vector3 pos; }
- 接下來我們在save程式片段內,建立一個playerState類型的資料「myPlayer」,
並且將資料寫入myPlayer:public void save() { //填寫jplayerState格式的資料.. playerState myPlayer = new playerState(); myPlayer.name = "sammaru"; myPlayer.level = 87; myPlayer.pos = GameObject.Find("sammaru").transform.position; }
- 接下來,我們繼續在save中,加入把myPlayer資料轉成json的代碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public void save() { //填寫jplayerState格式的資料.. playerState myPlayer = new playerState(); myPlayer.name = "sammaru"; myPlayer.level = 87; myPlayer.pos = GameObject.Find("sammaru").transform.position; //將myPlayer轉換成json格式的字串 string saveString = JsonUtility.ToJson(myPlayer); //將字串saveString存到硬碟中 StreamWriter file = new StreamWriter(System.IO.Path.Combine(Application.streamingAssetsPath, "myPlayer")); file.Write(saveString); file.Close(); }
- 上述程式碼不但將myPlayer轉存成字串saveString,還透過StreamWrite將資料存到硬碟。
為了要使用StreamWrite,必須在程式碼開頭載入相關資源:using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; //StreamWrite會用到
- 開啟並執行在本文提供的範例檔,
在執行狀態中擊該按鈕SAVE,會在Asset/Resources資料夾內產生的myPlayer.json檔案。
剛檔案的內容如下:{"name":"sammaru","level":87,"pos":{"x":0.0,"y":0.0,"z":500.0}}
- 格式化後看起來是這樣,存檔成功!
{ "name": "sammaru", "level": 87, "pos": { "x": 0.0, "y": 0.0, "z": 500.0 } }
[狀態讀檔]
- 在load函式中,我們填入下面程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
public void load() { //讀取json檔案並轉存成文字格式 StreamReader file = new StreamReader(System.IO.Path.Combine(Application.streamingAssetsPath, "myPlayer")); string loadJson = file.ReadToEnd(); file.Close(); //新增一個物件類型為playerState的變數 loadData playerState loadData = new playerState(); //使用JsonUtillty的FromJson方法將存文字轉成Json loadData = JsonUtility.FromJson<playerState>(loadJson); //驗證用,將sammaru的位置變更為json內紀錄的位置 GameObject.Find("sammaru").transform.position = loadData.pos; }
- 上述程式碼,是透過StreamRead讀取遊戲目錄路內的myPlayer.json。
並透過JsonUtility的FromJson將字串解析成物件。 - 大家玩玩可以下載本文提供的範例檔,
透過WASD可以改變sammaru的位置,
並可按save紀錄其位置,按Load將sammaru還原至按save按鈕時的位置。
接下來我們在save程式片段內,建立一個playerState類型的資料「myPlayer」,
回覆刪除並且將資料寫入myPlayer:
public void save()
{
//填寫jplayerState格"式"的資料..
playerState myPlayer = new playerState();
myPlayer.name = "sammaru";
....
*有錯字 格「式」
5.6.都有 格「式」可以改XD
刪除在load函式中 那邊,上方應該是 狀態載檔吧?
最後...感謝教學!!!
感謝回覆~ 有錯字真是真是不好意思! 有任何錯誤都麻煩提出囉
刪除再次感謝回覆! 因為你本教學會變更好~~~~~
進到遊戲,還沒Save就Load的話,會出現錯誤
刪除NullReferenceException: Object reference not set to an instance of an object
下載的範例檔有做修正了,沒想到是錯在我後來多寫的方法 syncInfo();
刪除基本上應該是沒問題了:)
刪除我在Start() 那邊加入load();
這樣進入就直接是上次的位置
然後button是故意用在鏡頭外面嗎XD
感謝教學!! 這樣應該就沒問題了!
然後button是故意用在鏡頭外面嗎XD
刪除~~疑疑疑,晚點偷改一下
哈哈! 然後最後的建構元 還沒用到
刪除public playerState(string n, int l, Vector3 p)
這是之後也許會用到加上去的吧?
如果沒有什麼問題的話...那個建構元就放著吧 ^_^
刪除想請問山姆大,如果要用Json儲存遊戲中所有物品資料
回覆刪除該如何去執行?
有沒有實際狀況可以舉例?我在依照你的舉利用個範例會比較直接
刪除作者已經移除這則留言。
刪除目前想在同個json中存取多個物品資料
刪除{
"itemID": 0,
"itemName": "Test00",
"itemType": "Test",
"itemDesc": "TestDesc"
}
查了資料後使用了這樣的方式去紀錄多個檔案
[
{"Name": Hi01}
{"Name": Hi02}
]
可是卻不曉得如何存入List中
另外想請問JsonUtility是否不支援中文內容,嘗試後都會變為亂碼 (?
按到刪除 (艸
中文的問題已經解決,貌似是我的VS跳成ANSI編碼
刪除改回UTF-8就可以了 <3
最後一個問題也解決了,原來只是我腦抽會錯意
刪除文章告訴我的是宣告陣列也就是要寫成
{
"items":
[
"Items/Tools/hoe.json"
]
}
打擾了抱歉 (#
不要覺得打擾啦 沒人留言我很無聊耶!!
刪除你是想知道如何把List存入Json中嗎? ^^
其實大致上的概念我都懂,只是很死腦經XD
刪除卡在一個自己無法理解的點,就壞光光了!!
現在解決了問題,發問後問題自然就理順了 (?!
Great! 恭喜你解題成功
刪除請問這個可以在android上執行嗎? 它的路徑好像不能設在 Application.persistentDataPath 會拒絕存取。
回覆刪除還有使用內建的跟額外用LitJSON會有甚麼差別?
1. 路徑問題:
刪除http://answers.unity3d.com/questions/1171740/android-devices-does-not-read-json-file-but-unity.html
看上面文章的討論,看來是要用 Resources.Load 的方式,去讀取放在Assets/Resources/ 的json檔案
2. 跟LitJSON的差別
http://jacksondunstan.com/articles/3303
看這篇的敘述,應該是內建的快很多
請問如何將json load()出來之後 在他底下一個新的數組 再save()回去
回覆刪除因為我想寫個類似儲存卡牌的json檔 但卻摸不著頭緒
很高興看到有人提問!!
刪除不過我有點不太明白你的意思 ,
可以再講詳細一點嗎 ?
將json檔讀取出
刪除{"GirlID":1,
"GirlName":"AAA",
"Girlstar":5,
"GirlLevel":1}
之後 加入一筆新的
{"GirlID":2,
"GirlName":"BBB",
"Girlstar":4,
"GirlLevel":1}
再儲存回去原本的json檔中
應該說把一筆資料新增道便兩筆資料
https://goo.gl/fW6eek
刪除我寫了一個簡單的範例給你。
這份範例裡面已經新增了四份資料GirlName資料
分別是 Rose,Apple,Cindy,Gigi
你可以透過下方的輸入框輸入GirlName即可查詢出對應的GirlLevel。
或是你可以試著用上方的輸入框部分。自行新增新的GirlName以及該Girl的Level
謝謝山姆大,看過一次就懂了
刪除跟我想的寫法完全不一樣,但是非常簡單!
山姆大 請問unity build的時候 要怎麼將json一起build出來
回覆刪除OK 我測試了一下。json其實是有被Build出來的。 只是被封裝了起來,目前的寫法會讀取不到 @@
刪除所以我網站上提供的讀檔方式 改成下面這段就可以了:
public void load()
{
//讀取json檔案並轉存成文字格式
TextAsset file = Resources.Load("myPlayer") as TextAsset;
string loadJson = file.text;
//新增一個物件類型為playerState的變數 loadData
playerState loadData = new playerState();
//使用JsonUtillty的FromJson方法將存文字轉成Json
loadData = JsonUtility.FromJson(loadJson);
//驗證用,將sammaru的位置變更為json內紀錄的位置
GameObject.Find("sammaru").transform.position = loadData.pos;
}
================
重點就在於要把原本的:
StreamReader file = new StreamReader(Application.dataPath + "/Resources/myPlayer.json");
改成
TextAsset file = Resources.Load("myPlayer") as TextAsset;
再把
string loadJson = file.ReadToEnd();
改成
string loadJson = file.text;
然後 file.Close(); 可以刪掉了,用不到了。
你再試試看唷 ^_^
謝山姆大 >_< 馬上解決
刪除我後來再多試了一下 這樣解還是怪怪的。
刪除雖然放在Resources資料夾下會被封裝包起來,但是沒辦法再寫入@@
(至少我查了一下好像沒辦法)
所以我直接再換一個做法,就可以讓json包出去了。
你再看看網頁上面新的程式碼還有範例吧
山姆大 我又來了 >_<
回覆刪除我根據您上次所說的
把 StreamReader file = new StreamReader(Application.dataPath + "/Resources/myPlayer.json");
改成 TextAsset file = Resources.Load("myPlayer") as TextAsset;
在電腦上面執行是沒問題的
但是當我包成apk檔放到手機上執行 不知到哪邊有錯誤 我手機上讀取不到json的檔案
所以整個檔案有用到json的地方全部不會顯示
再次感謝山姆大 >_<
OK 我新增了第三個範例檔了,我自己測過在安桌環境上面可讀可寫了。
刪除您測試有問題或沒問題也麻煩跟我說一下嘿!
我需要的是把json檔一起包進去 所以我可能沒辦法使用這個
刪除那你可以把要讀的Json放在Resources資料夾內。
刪除用Resources.Load的方式讀取。
https://answers.unity.com/questions/1092940/loading-json-as-a-text-asset-using-resourcesload.html
抱歉 山姆大 我忘記說還有save的部分
刪除load的部分 我暫時用好了 只是不確定有沒有完成
我也從你給的網頁裡面的去找save的部分 但看到很多人問了關於save json on android 都沒人去回答 或是回答的不完整(有錯誤) 我沒辦法參考 所以再次向您請教
突然換成馬力歐的頭像讓我以為是哪位跑來幫您解答 >_<
你可以第一次load從Resources.Load的方式讀取。
刪除然後之後的讀寫檔案的用Application.persistentDataPath
這樣應該就沒問題了吧!
所以是先用Resources.Load讀取出來
刪除儲存到Application.persistentDataPath 之後都從這邊提取對巴
謝山姆大的提點
OKOK !
刪除您好,我寫了一封信詢問問題,想請您幫我看看
回覆刪除