เข้าถึง Unity StreamingAssets บน Android

ฉันเขียนโค้ดเพื่อรับโฟลเดอร์ทั้งหมดภายในโฟลเดอร์ภายใน StreamingAssets จากนั้นรับไฟล์ทั้งหมดในโฟลเดอร์นั้น มันทำงานได้ดีบน Windows แต่ฉันไม่สามารถใช้งานบน Android ได้

นี่คือรหัส:

foreach (string s in Directory.GetDirectories(model.path + "/Levels")) {
        GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
        el.transform.SetParent(grid1.transform);
        string[] words = s.Split('/');
        #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
                            words = s.Split('\\');
        #endif
        el.GetComponentInChildren<Text>().text = words[words.Length - 1];
        el.GetComponent<Button>().onClick.AddListener(() => {
            MapSizeButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
        });
    }

ฉันต้องเพิ่ม #if UNITY_STANDALONE_WIN สำหรับ windows เนื่องจาก '\'

จากนั้นสำหรับไฟล์ในโฟลเดอร์นั้นฉันเขียนสิ่งนี้:

foreach (string s in Directory.GetFiles(model.path + "/Levels/" + model.mapSize + "/" + model.colorNumber)) {
        string[] words = s.Split('/');
        #if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
                    words = s.Split('\\');
        #endif
        words = words[words.Length - 1].Split('.');
        if (words[1] == "json") {
            GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
            el.transform.SetParent(grid3.transform);
            el.GetComponentInChildren<Text>().text = words[0];
            el.GetComponent<Button>().onClick.AddListener(() => {
                levelButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
            });
        }
    }

ฉันใช้ UnityEngine.UI.Directory แต่ฉันอ่านมาว่าไม่สามารถใช้บน Android ได้ และฉันต้องใช้ WWW แทน บางสิ่งเช่นนี้:

string xmlSetUpPath = "jar:file://" + Application.dataPath + "!/assets/xml/xmlSetUp.xml";

        WWW book1WWW = new WWW(book1Path);
        yield return book1WWW;
        if(!File.Exists(Application.persistentDataPath + "/xml/book1.xml"))
        {
            File.WriteAllBytes(Application.persistentDataPath + "/xml/book1.xml", book1WWW.bytes); 
        }

อย่างไรก็ตาม ฉันไม่พบสิ่งใดเช่น Directory.getFiles() หรือ Directory.getFolder() ดังนั้นฉันจึงคิดว่าฉันสามารถใช้ WWW เพื่อตรวจสอบว่ามีไฟล์อยู่หรือไม่ (เนื่องจากชื่อไฟล์คือ 1.json, 2.json, 3.json) และวนซ้ำจนกว่าจะไม่มีไฟล์อยู่

แต่ฉันจะต้องตรวจสอบด้วยว่ามีโฟลเดอร์สำหรับส่วนที่ 1 ของสคริปต์หรือไม่ และฉันไม่สามารถค้นหาวิธีตรวจสอบว่ามีโฟลเดอร์อยู่ใน WWW หรือไม่ (ชื่อโฟลเดอร์ของฉันคือ 1,2,3,4...)

แล้วจะตรวจสอบได้อย่างไรว่ามีโฟลเดอร์อยู่กับ WWW หรือไม่?

หรือฉันจะทำอะไรได้อีก?

อัปเดต :

ฉันอัปเดตโค้ดแล้ว ตอนนี้ดูเหมือนว่า:

for (int i = 0; i < 100; i++) {
        if (Directory.Exists(Path.Combine(model.path, "Levels/" + i.ToString()))){
            GameObject el = (GameObject)Instantiate(listButton, Vector3.zero, Quaternion.identity);
            el.transform.SetParent(grid1.transform);
            el.GetComponentInChildren<Text>().text = i.ToString();
            el.GetComponent<Button>().onClick.AddListener(() => {
                MapSizeButtonClick(Int32.Parse(el.GetComponentInChildren<Text>().text));
            });
        }
    }

ฉันใช้ path.combine() และตรวจสอบทุกโฟลเดอร์ตั้งแต่ 0 ถึง 100 มันใช้งานได้บน Windows แต่ก็ยังใช้งานไม่ได้ใน Android

เส้นทางถูกกำหนดไว้ดังนี้:

#if UNITY_IPHONE
        path = Application.dataPath + "/Raw";
    #endif

    #if UNITY_ANDROID
        path = "jar:file://" + Application.dataPath + "!/assets";
    #endif

    #if UNITY_STANDALONE || UNITY_EDITOR
        path = Application.dataPath + "/StreamingAssets";
    #endif

การอัปเดตคำถาม

ฉันสร้างสคริปต์ที่สร้างเส้นทางของไฟล์ เส้นทางจะเหมือนกันเสมอ: "FolderNumerotedFromYToX/FolderNumerotedFromYToX/FileNumerotedFrom1ToX.json" การสร้างใช้งานได้ แต่การเขียนถึง JSON ไม่ได้ มันส่งออก "{}"

        // Generate level list
    List<KeyValuePair<int, List<KeyValuePair<int, List<int>>>>> l;
    l = new List<KeyValuePair<int, List<KeyValuePair<int, List<int>>>>>();
    for (int i = 1; i < 100; i++) {
        if (Directory.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i.ToString()))) {
            l.Add(new KeyValuePair<int, List<KeyValuePair<int, List<int>>>>(i, new List<KeyValuePair<int, List<int>>>()));
            for (int j = 1; j < 100; j++) {
                if (Directory.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i + "/" + j))) {
                    l[l.Count - 1].Value.Add(new KeyValuePair<int, List<int>>(j, new List<int>()));
                    int k = 1;
                    while (true) {
                        if (File.Exists(Path.Combine(Path.Combine(Application.dataPath, "StreamingAssets"), "Levels/" + i + "/" + j + "/" + k + ".json"))) {
                            l[l.Count - 1].Value[l[l.Count - 1].Value.Count - 1].Value.Add(k);
                        }
                        else
                            break;
                        k++;
                    }
                }
            }
        }
    }
    string ljson = JsonUtility.ToJson(l);
    var lsr = File.CreateText("Assets/StreamingAssets/levels.json");
    lsr.WriteLine(ljson);
    lsr.Close();

คุณช่วยฉันหาวิธีจัดเก็บสิ่งนี้ลงในไฟล์ได้ไหม


person Elbbard    schedule 23.02.2016    source แหล่งที่มา
comment
IMO คุณควรใช้ Path.Combine() เพื่อเชื่อมเส้นทางที่ถูกต้องเข้ากับสตริง และคุณอ่านที่ไหนว่าคุณไม่สามารถใช้การดำเนินการไฟล์ปกติได้? File.Exists() น่าจะทำงานได้ดี   -  person LorDFaKeR    schedule 23.02.2016
comment
ฉันจะลอง Path.Combine() ขอบคุณ! ฉันอ่านที่นี่ forum.unity3d .com/threads/ และที่อื่นๆ พวกเขาบอกว่าคุณต้องใช้ WWW บน Android บางทีฉันอาจจะสับสนเล็กน้อย File.Exists() น่าจะใช้ได้ แต่มันเกี่ยวกับ Directory.GetFiles() และ Directory.GetFolders()   -  person Elbbard    schedule 23.02.2016
comment
โดยพื้นฐานแล้ว คุณ ต้องและสามารถใช้ได้เท่านั้น Application.persistentDataPath ในทุกกรณี - ทุกแพลตฟอร์ม - ทุกที่ - ไม่ว่าจะอย่างไรก็ตาม   -  person Fattie    schedule 23.02.2016
comment
เหตุใดฉันจึงควรใช้persistentDataPath ฉันใช้ Application.dataPath เหมือนที่กล่าวไว้ในเอกสารประกอบของ Unity docs.unity3d.com/Manual/StreamingAssets.html   -  person Elbbard    schedule 23.02.2016
comment
ฉันได้อัปเดตด้วยรหัสใหม่ในโพสต์   -  person Elbbard    schedule 23.02.2016
comment
หากใครเชื่อถือเอกสาร Unity อารยธรรมก็จะล่มสลาย   -  person Fattie    schedule 23.02.2016
comment
ถ้าฉันเขียน path = Application.persistentDataPath + /StreamingAssets มันจะไม่ทำงานบน Windows PersistantDataPath มีโฟลเดอร์รูทของโปรเจ็กต์และฉันต้องการโฟลเดอร์ Assets   -  person Elbbard    schedule 23.02.2016
comment
ฉันเพิ่งรู้ว่า dataPath เป็นเส้นทางไปยังโครงการและ PersistantDataPath เป็นเส้นทางไปยังบิลด์ (ใน appData บน Windows) แต่โฟลเดอร์นี้จะว่างเปล่าเมื่อฉันสร้างในตัวแก้ไข ดังนั้นฉันเดาว่าฉันควรใช้ #if UNITY_EDITOR เมื่อฉันสร้างในตัวแก้ไข   -  person Elbbard    schedule 23.02.2016
comment
ฉันใช้รหัสนี้สำหรับเส้นทางไปยัง StreamingAssets : path = Application.persistentDataPath + /assets/StreamingAssets; มันใช้งานไม่ได้และpersistDataPath มี /data/data/com.Project.Puzzle/files/ โทรศัพท์ของฉันไม่ได้รูท และฉันไม่สามารถเข้าไปในโฟลเดอร์นี้ได้   -  person Elbbard    schedule 23.02.2016
comment
ฉันเริ่มเหนื่อยกับการค้นหา... (มากกว่า 4 ชั่วโมงแล้ว) ฉันพบโค้ดอื่นที่พวกเขาใช้ Application.streamingAssets snip2code.com/Snippet/14142/ . ฉันควรใช้สิ่งนี้หรือไม่?   -  person Elbbard    schedule 23.02.2016


คำตอบ (2)


อาจฟังดูยาก แต่คุณต้องใช้คลาส WWW เพื่อเข้าถึงไฟล์ของคุณจาก StreamingAssets บน Android

และคุณต้องเก็บรายชื่อไฟล์ของคุณไว้เพื่อให้สามารถเข้าถึงได้ เนื่องจากดูเหมือนจะไม่มีทางใช้บางอย่างเช่น File.Exists หรือ Directory.GetFiles

ตัวอย่าง:

WWW www = new WWW(source);
yield return www;

if (string.IsNullOrEmpty(www.error))
{
    // make sure the destination directory exists
    File.WriteAllBytes(destination, www.bytes); 
}
else
{
    // error handling
}

เส้นทางไฟล์ต้นฉบับ (ฐาน) ของคุณควรมีลักษณะดังนี้: jar:file://" + Application.dataPath + "!/assets/


จากเอกสาร:

โปรดทราบว่าบน Android ไฟล์จะอยู่ภายในไฟล์ .jar ที่บีบอัด (ซึ่งโดยพื้นฐานแล้วเป็นรูปแบบเดียวกับไฟล์บีบอัด zip มาตรฐาน) ซึ่งหมายความว่าหากคุณไม่ได้ใช้คลาส WWW ของ Unity เพื่อดึงไฟล์ คุณจะต้องใช้ซอฟต์แวร์เพิ่มเติมเพื่อดูภายในไฟล์เก็บถาวร .jar และรับไฟล์

ที่มา: http://docs.unity3d.com/Manual/StreamingAssets.html

person d4Rk    schedule 23.02.2016
comment
ฉันสร้างสคริปต์ที่สร้างรายการไฟล์ (เพิ่มในโพสต์) แต่ตอนนี้ฉันไม่รู้วิธีเก็บไว้ในไฟล์ ส่วน JSON ไม่ทำงานและเพิ่งเขียน {} ลงในไฟล์ คุณสามารถช่วยฉันได้ไหม ? - person Elbbard; 24.02.2016
comment
ตอนนี้คุณสามารถโหลด/อ่านไฟล์บน Android ได้หรือไม่? นั่นเป็นคำถามที่แท้จริงใช่ไหม แต่โอเค .. คุณสร้างสิ่ง JSON ระหว่างรันไทม์หรือไม่? หากเป็นเช่นนั้น คุณไม่ควรใส่ไว้ใน Streaming Assets... ใช้ Application.persistentDataPath สำหรับข้อมูลดังกล่าว - person d4Rk; 24.02.2016

เพื่อแก้ไขปัญหานี้ ฉันได้สร้างสคริปต์การคอมไพล์ล่วงหน้าซึ่งจะทำงานก่อนการคอมไพล์ สคริปต์นี้จะแสดงรายการชื่อไฟล์ที่คุณต้องการเข้าถึงในภายหลังในไฟล์ข้อความ

 #if UNITY_EDITOR
 using UnityEditor.Build;
 using UnityEditor;
 using System.IO;

 public class BM_AndroidBuildPrepartion : IPreprocessBuild
 {
     public int callbackOrder { get { return 0; } }
     public void OnPreprocessBuild(BuildTarget target, string path)
     {
         // Do the preprocessing here
         string[] fileEntries = Directory.GetFiles("Assets/Resources/Prefabs/alphabet", "*.prefab");
         System.IO.Directory.CreateDirectory("Assets/StreamingAssets/");
         using (StreamWriter sw = new StreamWriter("Assets/StreamingAssets/alphabet.txt", false))
         {

         foreach (string filename in fileEntries) {
                 sw.WriteLine(Path.GetFileNameWithoutExtension(filename));
         }

         }
     }
 }
 #endif

จากนั้นฉันก็อ่านไฟล์ข้อความและคุณสามารถเข้าถึงไฟล์ได้ในลักษณะเดียวกัน แต่คุณต้องวางไว้ในโปรเจ็กต์ของคุณใน Assets/StreamingAssets/

#if UNITY_ANDROID
        string  path = "jar:file://" + Application.dataPath + "!/assets/alphabet.txt";
          WWW wwwfile = new WWW(path);
          while (!wwwfile.isDone) { }
          var filepath = string.Format("{0}/{1}", Application.persistentDataPath, "alphabet.t");
          File.WriteAllBytes(filepath, wwwfile.bytes);

          StreamReader wr = new StreamReader(filepath);
              string line;
              while ((line = wr.ReadLine()) != null)
              {
              //your code
              }
   #endif
person Shady Mohamed Sherif    schedule 04.07.2017