Akses Unity StreamingAssets di Android

Saya menulis beberapa kode untuk mendapatkan semua folder di dalam folder di dalam StreamingAssets dan kemudian untuk mendapatkan semua file di folder itu. Ini berfungsi dengan baik di Windows tetapi saya tidak bisa membuatnya berfungsi di Android.

Ini kodenya:

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));
        });
    }

Saya harus menambahkan #if UNITY_STANDALONE_WIN untuk windows karena '\'.

Kemudian untuk file di dalam folder itu saya menulis ini:

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));
            });
        }
    }

Saya menggunakan UnityEngine.UI.Directory tetapi saya membacanya tidak dapat digunakan di Android dan saya harus menggunakan WWW. Sesuatu seperti ini :

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); 
        }

Namun saya tidak dapat menemukan yang seperti Directory.getFiles() atau Directory.getFolder(). Jadi saya pikir saya bisa menggunakan WWW untuk memeriksa apakah file tersebut ada (karena nama filenya adalah 1.json, 2.json, 3.json) dan mengulanginya hingga file tidak ada.

Tetapi saya juga perlu memeriksa apakah ada folder untuk bagian pertama skrip dan saya tidak dapat menemukan cara memeriksa apakah ada folder dengan WWW. (Nama folder saya juga 1,2,3,4...)

Jadi bagaimana cara memeriksa apakah ada folder dengan WWW?

Atau apa lagi yang bisa saya lakukan?

PEMBARUAN :

Saya memperbarui kodenya, sekarang terlihat seperti ini:

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));
            });
        }
    }

Saya menggunakan path.combine() dan memeriksa setiap folder dari 0 hingga 100. Ini berfungsi di Windows tetapi masih tidak berfungsi di Android.

Jalurnya diatur seperti ini:

#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

PEMBARUAN PERTANYAAN

Saya membuat skrip yang menghasilkan jalur file. Jalurnya selalu sama: "FolderNumerotedFromYToX/FolderNumerotedFromYToX/FileNumerotedFrom1ToX.json". Pembuatannya berfungsi tetapi penulisan ke JSON tidak. Ini menghasilkan "{}".

        // 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();

Bisakah Anda membantu saya menemukan cara untuk menyimpannya ke file?


person Elbbard    schedule 23.02.2016    source sumber
comment
IMO Anda harus menggunakan Path.Combine() untuk menggabungkan jalur yang valid ke sebuah string. Dan di mana Anda membaca bahwa Anda tidak dapat menggunakan operasi File normal? File.Exists() seharusnya berfungsi dengan baik.   -  person LorDFaKeR    schedule 23.02.2016
comment
Saya akan mencoba Path.Combine(), terima kasih! Saya membacanya di sini forum.unity3d .com/threads/ dan di tempat lain, mereka mengatakan Anda harus menggunakan WWW di Android. Mungkin saya sedikit bingung, File.Exists() seharusnya berfungsi tetapi ini tentang Directory.GetFiles() dan Directory.GetFolders().   -  person Elbbard    schedule 23.02.2016
comment
pada dasarnya Anda harus dan hanya dapat menggunakan Application.persistentDataPath di semua kasus - semua platform - di mana pun - apa pun yang terjadi.   -  person Fattie    schedule 23.02.2016
comment
Mengapa saya harus menggunakan persistenDataPath ? Saya menggunakan Application.dataPath seperti yang disebutkan dalam dokumentasi Unity. docs.unity3d.com/Manual/StreamingAssets.html   -  person Elbbard    schedule 23.02.2016
comment
Saya membuat pembaruan dengan kode baru di postingan.   -  person Elbbard    schedule 23.02.2016
comment
jika ada yang mempercayai dokumentasi Unity, peradaban akan runtuh.   -  person Fattie    schedule 23.02.2016
comment
Jika saya menulis path = Application.persistentDataPath + /StreamingAssets tidak berfungsi di Windows. PersistantDataPath berisi folder root proyek dan saya ingin folder Aset.   -  person Elbbard    schedule 23.02.2016
comment
Saya baru menyadari bahwa dataPath adalah jalur menuju proyek dan PersistantDataPath adalah jalur menuju build (di appData di Windows). Tetapi folder ini kosong ketika saya membuat editor jadi saya rasa saya harus menggunakan #if UNITY_EDITOR ketika saya membuat editor.   -  person Elbbard    schedule 23.02.2016
comment
Saya menggunakan kode ini untuk jalur ke StreamingAssets : path = Application.persistentDataPath + /assets/StreamingAssets;. Itu tidak berfungsi dan persistenDataPath berisi /data/data/com.Project.Puzzle/files/. Ponsel saya belum di-root dan saya tidak bisa masuk ke folder ini.   -  person Elbbard    schedule 23.02.2016
comment
Saya lelah mencari... (sekarang lebih dari 4 jam) Saya menemukan kode lain yang menggunakan Application.streamingAssets. snip2code.com/Snippet/14142/ . Haruskah saya menggunakan ini?   -  person Elbbard    schedule 23.02.2016


Jawaban (2)


Ini mungkin terdengar sulit, tetapi Anda benar-benar harus menggunakan kelas WWW untuk mengakses file Anda dari StreamingAssets di Android.

Dan Anda harus menyimpan daftar nama file Anda, agar dapat mengaksesnya, karena sepertinya tidak ada cara untuk menggunakan sesuatu seperti File.Exists atau Directory.GetFiles.

Contoh:

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
}

Jalur file sumber (dasar) Anda akan terlihat seperti ini: jar:file://" + Application.dataPath + "!/assets/


Dari dokumen:

Perhatikan bahwa di Android, file-file tersebut terkandung dalam file .jar terkompresi (yang pada dasarnya formatnya sama dengan file terkompresi zip standar). Artinya, jika Anda tidak menggunakan kelas WWW Unity untuk mengambil file, maka Anda perlu menggunakan perangkat lunak tambahan untuk melihat ke dalam arsip .jar dan mendapatkan file tersebut.

Sumber: http://docs.unity3d.com/Manual/StreamingAssets.html

person d4Rk    schedule 23.02.2016
comment
Saya membuat skrip yang menghasilkan daftar file (Ditambahkan ke posting). Tapi sekarang saya tidak tahu cara menyimpannya dalam file. Bagian JSON tidak berfungsi dan hanya menulis {} ke file. Bisakah kamu membantuku ? - person Elbbard; 24.02.2016
comment
Apakah Anda dapat memuat/membaca file di Android sekarang? Itu adalah pertanyaan sebenarnya, bukan? Tapi oke.. apakah Anda membuat barang JSON saat runtime? Jika demikian, Anda sebaiknya tidak memasukkannya ke dalam Aset Streaming.. Gunakan Application.persistentDataPath untuk data tersebut. - person d4Rk; 24.02.2016

Untuk mengatasi masalah ini saya membuat skrip pra-kompilasi yang akan dijalankan sebelum kompilasi; skrip ini akan mencantumkan nama file yang ingin Anda akses nanti dalam file teks

 #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

lalu saya membaca file teks dan Anda dapat mengakses file dengan cara yang sama tetapi Anda harus memasukkannya ke dalam proyek Anda di 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