在Unity中,如何以适用于Android的方式从json文件填充此allRoundData数组?

时间:2017-02-07 15:43:07

标签: android json unity3d

我是Unity和Android开发的新手,但请不要将其标记为重复 - 我已经在堆栈中查找了答案,但类似的主题和问题并没有产生任何有效的解决方案,或者想要细节,或过时,或似乎不符合我的具体需要。

好的,我有一个测验应用程序,建立在第1部分和第1部分之后。 this tutorial中的2个。该链接包含任何人可能需要参考的所有源文件,并且在ios和统一编辑器中一切正常,fyi。

麻烦在于Android中的DataController脚本中的loadGameData函数。同样,在iOS和统一编辑器中一切正常,但是当我制作Android sdk时,测验是空白的,控制台说数据无法加载。 以下是当前函数的编写方式(教程链接中的完整文件):

    private void LoadGameData ()
{
    string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);


    if (File.Exists (result)) 
    {
        string dataAsJson = File.ReadAllText (result);
    GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);

    allRoundData = loadedData.allRoundData;

    }  // #if(File.Exists...

    else 
    {
    Debug.LogError ("Cannot load game data!");
    }  // #else

} // #LoadGameData

如果您查看same tutorial on youtube,您会发现很多人都注意到了Android版本的相同问题并且没有得到答复。统一论坛也是如此 - 这就是为什么我不认为这个问题是重复的原因,并且可能对类似情况下的其他人有所帮助。

我发现Android在这方面总是很棘手,而且习惯了以不同方式访问基于平台的文件,但是现在“Application.streamingAssetsPath”应该在任何平台上找到流媒体资产目录,甚至机器人。

我还学到了在android中,即使路径正确,文件也会被压缩,只会返回一个url。所以url需要使用unity的WWW类进行转换。我明白了,但是到目前为止,我还没有能够重新编写我的loadGameData函数来正常工作并加载allRoundData数组。

以下是我尝试过的一些例子:

IEnumerator androidData() 
{
    string filePath = Path.Combine (Application.streamingAssetsPath, gameDataFileName);
    if (filePath.Contains("://")) 
    {
        WWW www = new WWW(filePath);
        yield return www;
        result = www.text;
    } // #if(filePath.Contains
} // #androidData


private void LoadGameData ()

{

    androidData();


    if (File.Exists (result)) 
    {

        string dataAsJson = File.ReadAllText (result);
    GameData loadedData = JsonUtility.FromJson<GameData> (dataAsJson);

    allRoundData = loadedData.allRoundData;

    }  // #if(File.Exists...
    else 
    {
    Debug.LogError ("Cannot load game data!");
    }  // #else
} // #LoadGameData

我知道我很接近,这可能很简单 - 但我似乎无法达到最终目标。有人可以帮我弄清楚如何编写loadGameData函数,以便在android上加载这个allRoundData数组吗?

示例代码非常棒,非常受欢迎,不仅仅是我,但我相信很多人也会很感激 - 谢谢!

更新 根据第一个答案,我测试了一些在统一编辑器上运行的代码,但在Android中崩溃了。在Unity编辑器中,我收到“文件已存在”消息。这是我测试过的代码: 已经有:private string gameDataFileName = "data.json"; 我在Start()中的loadGameDate上面添加了copyFile调用,并编写了复制文件和loadGameData函数,如此...

int copyFileToPersistentDataPath(string gameDataFileName)
{
    string persistentPath = Application.persistentDataPath + "/" + gameDataFileName;

    try
    {
        //Copy only if gameDataFileName does not exist  
        if (!System.IO.File.Exists(persistentPath))
        {
            string path = System.IO.Path.Combine(Application.streamingAssetsPath, gameDataFileName);
            WWW www = new WWW(path);
            while (!www.isDone) { }
            System.IO.File.WriteAllBytes(persistentPath, www.bytes);
            Debug.Log(gameDataFileName + " Successfully Copied File to " + persistentPath);
            return 1;
        }
        else
        {
            Debug.Log(gameDataFileName + " File already exist here. There is no need to copy it again");
            return 0;
        }
    }
    catch (Exception e)
    {
        Debug.Log(gameDataFileName + " Failed To Copy File. Reason: " + e.Message);
        return -1;
    }
}



private void LoadGameData ()
{


    string tempPath = Path.Combine(Application.persistentDataPath, gameDataFileName);

    string dataAsJson = File.ReadAllText(tempPath);
    GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
    allRoundData = loadedData.allRoundData;
    } // #LoadGameData

无论是否调用在编辑器中复制文件,这都可以工作,但在Android中崩溃。

2 个答案:

答案 0 :(得分:0)

至于加载和保存游戏,这是一个duplicate。我标记并删除了这个副本,因为重复问题中的答案没有解释如何从 StreamingAssets 文件夹中读取。它只讨论了保存和加载数据。

确保将写入权限设置为外部(SDCard)

enter image description here

要做的第一件事就是将文件从 StreamingAssets 复制到persistentDataPath位置。

我发现从Application.streamingAssetsPath读取数据有问题,但我使用两种方法来解决这个问题。

int copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
    string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;

    try
    {
        //Copy only if fileNameWithExtensionName does not exist  
        if (!System.IO.File.Exists(persistentPath))
        {
            string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
            WWW www = new WWW(path);
            while (!www.isDone) { }
            System.IO.File.WriteAllBytes(persistentPath, www.bytes);
            Debug.Log(fileNameWithExtensionName + " Successfully Copied File to " + persistentPath);
            return 1;
        }
        else
        {
            Debug.Log(fileNameWithExtensionName + " File already exist here. There is no need to copy it again");
            return 0;
        }
    }
    catch (Exception e)
    {
        Debug.Log(fileNameWithExtensionName + " Failed To Copy File. Reason: " + e.Message);
        return -1;
    }
}

如果这对您不起作用,请使用下面WebClient的方法:

void copyFileToPersistentDataPath(string fileNameWithExtensionName)
{
    string path = System.IO.Path.Combine(Application.streamingAssetsPath, fileNameWithExtensionName);
    string persistentPath = Application.persistentDataPath + "/" + fileNameWithExtensionName;

    Debug.Log("Dir: " + persistentPath);
    WebClient webClient = new WebClient();
    webClient.Proxy = null;

    webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(OnDownloadComplete);
    webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnUpdateDownloadProgress);

    Uri uri = new Uri(path);
    webClient.DownloadFileAsync(uri, persistentPath);
}

void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)
{
    Debug.Log("Finished Downloading: " + e.Error.Message);
}

void OnUpdateDownloadProgress(object sender, DownloadProgressChangedEventArgs e)
{
    Debug.Log("Uploading Progreess: " + e.ProgressPercentage);
}

文件复制用法

copyFileToPersistentDataPath("yourFileName.txt");

复制文件后,您可以读取并将其转换为Json,如下所示:

string fileNameWithExtensionName = "questionfile.txt";
string tempPath = Path.Combine(Application.persistentDataPath, fileNameWithExtensionName);

string dataAsJson = File.ReadAllText(fileNameWithExtensionName);
GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);

答案 1 :(得分:0)

我最终把文件放在一个Resources文件夹中,然后将resources.load一个json文件加载到一个文本资产中,并将其放入一个字符串中来解析路由。我现在有两个不同的加载函数,一个在ios等工作,另一个在android中工作。这是android函数(resourcesGameDataFile没有.json扩展名):

public void LoadDataForAndroid()
{

    TextAsset dataFile = Resources.Load(resourcesGameDataFile) as TextAsset;
    string dataAsJson = dataFile.ToString();
    GameData loadedData = JsonUtility.FromJson<GameData>(dataAsJson);
    allRoundData = loadedData.allRoundData;
    Debug.Log ("Android data loaded with" + resourcesGameDataFile);
} // #LoadDataForAndroid

这适用于统一编辑器和Bluestacks(android模拟器)。