Unity to WeChat mini-game local data storage
problem background
Recently, when converting Unity to a small game, I found that when reading and writing local files, using the Application.persistentDataPath
cache path to save the file failed because of the platform limitation of WebGL. Therefore, the original code for reading and writing local files needs to be modified according to the platform.
One of the easiest ways is to PlayerPrefs
store the content originally stored in the file and use it on the WebGL platform. For example, writing like this:
There PlayerPrefs
is a problem of slow reading for the first time, you can use the plug-in of WeChat Mini Game to add the used Key. How to use: WeChat Mini Game -> PlayerPrefs Optimization:
Therefore, when there are a lot of files or data to be stored, we still hope to complete the file reading and writing without modifying the original reading and writing logic as much as possible. So WeChat provided it to us WX.env.USER_DATA_PATH
.
WeChat mini game to read and write local files
After Unity is converted into a WeChat mini game File.WriteAllText
and File.ReadAllText
due to path problems, it does not take effect.
Instead, use the path provided by the WeChat mini game plug-in. The code in the plug-in:
The sample code is as follows:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using WeChatWASM;
public class SaveFile : MonoBehaviour
{
// 文件类型
private PlayerData m_PlayerData;
// 文件名称
private string fileName = "/PlayerData.txt";
private void OnGUI()
{
if (GUI.Button(new Rect(100, 100, 200, 200), "读取文件"))
{
LoadPlayerData();
}
if (GUI.Button(new Rect(100, 400, 200, 200), "写入文件"))
{
WritePlayerData();
}
}
/// <summary>
/// 读取文件
/// </summary>
private void LoadPlayerData()
{
#if UNITY_WEBGL
WXFileSystemManager fs = WX.GetFileSystemManager();
// 判断是否存在目录
if (fs.AccessSync(WX.env.USER_DATA_PATH + fileName).Equals("ok"))
{
// 读取内容
string playerDataString = fs.ReadFileSync(WX.env.USER_DATA_PATH + fileName, "utf-8");
if (playerDataString != "")
{
m_PlayerData = LitJson.JsonMapper.ToObject<PlayerData>(playerDataString);
}
}
Debug.Log($" 读取文件 姓名:{
m_PlayerData.name} 年龄:{
m_PlayerData.age}");
#endif
}
/// <summary>
/// 写入文件
/// </summary>
private void WritePlayerData()
{
m_PlayerData = new PlayerData();
m_PlayerData.name = "Czhenya";
m_PlayerData.age = 18;
Debug.Log($" 写入文件 姓名:{
m_PlayerData.name} 年龄:{
m_PlayerData.age}");
string playerData = LitJson.JsonMapper.ToJson(m_PlayerData);
#if UNITY_WEBGL
WXFileSystemManager fs = WX.GetFileSystemManager();
fs.WriteFileSync(WX.env.USER_DATA_PATH + fileName, playerData, "utf-8");
#endif
}
}
public class PlayerData
{
public string name;
public int age;
}
Test result:
The error of reading the file without checking whether the local directory exists:
You can see that the subsequent reading and saving are successful:
PS: If you only need to read files, the files under the StreamingAssets folder can be UnityWebRequest
read on the WebGL platform.
Some limitations of the WebGL platform
Due to platform limitations, some features are not supported on WebGL:
- Does not support multi-threading, because JavaScript does not support multi-threading, so do not use classes under the System.Threading namespace;
- Socket cannot be used directly, including any type under System.Net, some types under System.Net.Sockets, and UnityEngine.Network. If you need to use network functions on the WebGL platform, you can use WWW or UnityWebRequest, which are based on the Http protocol If you need high real-time performance, you can choose WebSockets or WebRTC;
- WebGL 1.0 is based on OpenGL ES 2.0, and WebGL 2.0 is based on OpenGL ES 3.0, so there are corresponding restrictions;
- WebGL is AOT (ahead of time, that is, a static compilation platform, so the types under System.Reflection.Emit cannot be used for code generation, and the same is true for IL2CPP and iOS.
Error viewing method sharing
After switching to the mini game, you can see the error log on the phone by turning on the debug mode. The error log is as follows:
exception thrown : Runtiseerror : null function orfunction signature ismatch . Rurtimcerror : nullfunction or function signature mismatch
Mini Progran Error null function or function signature mismatchRuntimeerror: null function or function signaturemismatc
These two paragraphs of error are triggered by the same problem. The first time I saw this kind of error report, I was at a loss and didn't know where to start. After looking down two lines, I found the function I wrote myself: the method ScreenRatiosFilter
in the class Fit
. I have already located the error reporting method, so I don’t need to talk about the following problems.
Now that you have seen this, let me tell you the secret : I really can’t tell where the error was reported, and it can’t be reproduced in the editor. Make up the log, and then reproduce the error, so that you can locate the specific error. The wrong number of lines was reported.
I also encountered a strange problem, and record it together. I hope it can inspire you: a piece of game logic only reports an error in the mini game, and the editor and other ends are fine. Later, I added a try...catch
capture once, did not do any other processing, and then it turned out to be easy to use...