我是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中崩溃。
答案 0 :(得分:0)
至于加载和保存游戏,这是一个duplicate。我标记并删除了这个副本,因为重复问题中的答案没有解释如何从 StreamingAssets 文件夹中读取。它只讨论了保存和加载数据。
确保将写入权限设置为外部(SDCard)。
要做的第一件事就是将文件从 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模拟器)。