Как перезагрузить ресурсы Unity, заполненные XML

Я заполняю несколько элементов, таких как ScrollView, данными из нескольких файлов XML. При нажатии кнопки с сервера загружаются самые последние файлы. Я пытаюсь отобразить их прямо в графическом интерфейсе, но мне всегда приходится перезапускать приложение, чтобы увидеть последнюю загруженную версию. Загрузка и запись работают корректно.

Вот код:

Сначала процесс загрузки/обновления

public bool update() {
    try {
        // Download + Save
        WebClient wc = new WebClient();
        wc.Credentials = new NetworkCredential("anonymous", "");
        wc.DownloadFile(_address_employeesXML, _filePathToXMLImport + "/employees.xml");

        XMLReader test = new XMLReader(logController);
        test.readXMLFiles(); 
        Debug.Log("Update successful");
    } catch (Exception e) {
        #if UNITY_EDITOR
        EditorUtility.DisplayDialog("Error",  e.Message, "OK");
        #endif
        XMLReader test = new XMLReader(logController);
        //test.readXMLFiles();
        Debug.LogException(e);
        return false;
    }
    return true;
}

затем процесс чтения:

    public bool readEmployees()
{
    string pathToEmployeeXML = _filePathToXMLImport + "/employees.xml";
    if (File.Exists(pathToEmployeeXML))
    {
        using (XmlReader reader = XmlReader.Create(pathToEmployeeXML))
        {
            while (reader.Read())
            {
                // Only detect start elements.
                if (reader.IsStartElement())
                {
                    switch(reader.Name)
                    {
                        case "employee":

                            XmlReader inner = reader.ReadSubtree();

                            inner.ReadToDescendant("firstName");
                            string firstName = inner.ReadElementString();
                            inner.ReadToDescendant("lastName");
                            string lastName = inner.ReadElementString();

                            generateEmployee(firstName, lastName);
                            break;
                    }
                }
            }
        }
        return true;
    }
    return false;
}

Я нашел эту тему: Перезагрузка ресурса XML в Unity Что, к сожалению, на самом деле не решает мою проблему.

Я также пытался использовать AssetDatabase.Refresh, но, честно говоря, так и не понял, как это реализовать.

Обновлено:

Итак, теперь я изменил его, чтобы использовать File.IO и загружать файлы асинхронно. Мне все еще нужно перезапустить приложение, чтобы увидеть изменения.

public class XMLController : MonoBehaviour {

public MessageLogsController logController;
public ApplicationStateSaver saver;

const string _address = "ftp://127.0.0.1:2121/";
const string _address_maintenancePlansXML = _address + "maintenancePlans.xml";
const string _address_employeesXML = _address + "employees.xml";
const string _address_materialsXML = _address + "materials.xml";
const string _address_machinesXML = _address + "machines.xml";
const string maintenancePlans = "maintenancePlans";
const string employees = "employees";
const string materials = "materials";
const string machines = "machines";
// Use this for initialization
void Start () {
    XMLReader XMLReader = new XMLReader(logController);

    StartCoroutine(GetXML(_address_maintenancePlansXML, maintenancePlans));
    StartCoroutine(GetXML(_address_employeesXML, employees));
    StartCoroutine(GetXML(_address_materialsXML, materials));
    StartCoroutine(GetXML(_address_machinesXML, machines));

    XMLReader.readXMLFiles();
    saver.Initialize();
}

public void WriteInformationToXML()
{
    XMLWriter writer = new XMLWriter();
    writer.writeXML();

}

IEnumerator GetXML(string link, string file_name) {
    UnityWebRequest www = UnityWebRequest.Get(link);

    yield return www.SendWebRequest();

    Debug.Log("Success");

    if (www.isNetworkError || www.isHttpError) {
        Debug.Log(www.error);
    }
    else {
        // Show results as text
        Debug.Log(www.downloadHandler.text);

        string savePath = string.Format("{0}/{1}.xml", Application.persistentDataPath + "/Files/XML/Import/", file_name);        
        System.IO.File.WriteAllText(savePath, www.downloadHandler.text);
        Debug.Log("Files written");

    }
}

Можете ли вы опубликовать код? Что вы пробовали? Как мы можем решить вашу проблему без дополнительной информации?

Ludovic Feltz 19.07.2019 14:36

Я добавил немного кода. Я просто пропускаю существующую функцию, которая помогает перезагружать холст/определенные активы без перезапуска приложения.

nicenoize 19.07.2019 15:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
201
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я бы предпочел сделать весь процесс асинхронным, чтобы не блокировать основной поток, используя UnityWebRequest для загрузки.

На самом деле вам не нужно писать в файл и читать его снова ... вы можете напрямую использовать загруженный string и передать его в XmlSerializer (вы должны реализовать класс, представляющий макет xml - см. Сохранение и загрузка данных: XmlSerializer).

Если вам все еще нужно/хотите писать, я бы написал в Application.persitentDataPath и прочитал/записал файл, используя FileStream

public void update(Action<bool> success)  
{
    StartCoroutine(UpdateRoutine(onSuccess)); 
}

private string authenticate(string username, string password) 
{
    string auth = username + ":" + password;
    auth = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(auth));
    auth = "Basic " + auth;
    return auth; 
}  

private IEnumerator UpdateRoutine (Action<bool> onSuccess) 
{   
    using(var www = UnityWebRequest.Get(_address_employeesXML)
    {
        string authorization = authenticate("YourUserName", "YourPassWord");
        www.SetRequestHeader("AUTHORIZATION", authorization);

        yield return www.SendRequest();

        if (www.error)
        {
             success?.Invoke(false);
        } 
        else
        {
            // you could ofcourse simply use the returned filecontent now like
            var xml = www.downloadHandler.text;

            var xmlSerializer = new XmlSerializer(typeof(YOURDATA_CLASS));

            var dataClass = (YOURDATA_CLASS) xmlSerializer.Deserialize(xml);
            success?.Invoke(true);


            // However if you prefer to write the file 
            WriteFile(xml, success);
        }
    }
}

// Usually async void is bad
// but with a callback its fine
private async void WriteFile(string xml, Action<bool> success)
{ 
    try
    {
        var data = Encoding.UTF8.GetBytes(xml);

        using(var file = File.Open(Path.Combine(_filePathToXMLImport, "employees.xml", FileMode.OpenOrCreate))
        {
            await file.WriteAsync(data, 0, data.length);

            success?.Invoke();
        }
    }
    catch
    {
        success?.Invoke(false);
    }
}      

затем процесс чтения:

public void ReadFile(Action<bool> success)
{
    using(var file = File.Open(Path.Combine(_filePathToXMLImport, "employees.xml", FileMode.Open))
    {
        var data = new byte[(int)file.length];
        await file.ReadAsync(data, 0, data.length);

        var xml = Encoding.UTF8.GetString(Data);

        var xmlSerializer = new XMLSerializer(typeof(YOURDATA_CLASS));

        var dataClass = (YOURDATA_CLASS) xmlSerializer.Deserialize(xml);
        success?.Invoke(true);
    }
}

Примечание. Набрано на смартфоне, поэтому гарантии нет, но я надеюсь, что идея понятна.

Спасибо за ответ. Я реализовал процесс асинхронной выборки. Я также пишу в Application.persitentDataPath, но, к сожалению, мне все еще нужно перезапустить приложение, чтобы обновить активы.

nicenoize 23.07.2019 16:17

ваш код работал отлично, я просто выполнил его с ложной точки.

nicenoize 01.08.2019 13:32
Ответ принят как подходящий

Решением моей проблемы стало перемещение упомянутого выше кода в класс Controller, отвечающий за StartView.

Другие вопросы по теме