Динамическое обновление ассетов означает, замена оных во время выполнения приложения, эта функциональность довольно полезна при отладке и настройке игры.
Первое, что мы сделаем это определим общую основу для всех ассетов, которые должны будут обновляться динамически. Все что нам нужно изначально, это путь к исходному файлу, где у нас располагается ассет и дата его создания. Создадим базовый абстрактный класс, с абстрактным методом Load, который и будет содержать свойства загружаемого файла:
Далее создадим Game Component , который будет отслеживать изменение фокуса главного игрового окна и при активации окна перезагружать обновившиеся файлы.
publicclass AutoReloadedAssetManager : DrawableGameComponent{privatereadonly List<AutoReloadedAsset> assets =new List<AutoReloadedAsset>();privatebool loaded;public ReadOnlyCollection<AutoReloadedAsset> Assets { get;private set;}public AutoReloadedAssetManager(Game game):base(game){ Assets =new ReadOnlyCollection<AutoReloadedAsset>(assets);// используем событие Activated чтобы занть// когда пользователь вернулся в игру game.Activated+= game_Activated;}publicvoid AddAsset(AutoReloadedAsset asset){if(assets.Contains(asset)) return; assets.Add(asset);if(loaded){ asset.FileWriteDate= File.GetLastWriteTime(asset.FilePath); asset.Load(GraphicsDevice);}}publicbool RemoveAsset(AutoReloadedAsset asset){return assets.Remove(asset);}protectedoverridevoid LoadContent(){foreach(var a in Assets){ a.FileWriteDate= File.GetLastWriteTime(a.FilePath); a.Load(GraphicsDevice);} loaded = true;}void game_Activated(object sender, EventArgs e){foreach(var a in Assets){ DateTime fileWriteDate = File.GetLastWriteTime(a.FilePath);if(fileWriteDate.CompareTo(a.FileWriteDate)>0){ a.FileWriteDate= fileWriteDate; a.Load(GraphicsDevice);}}}}
Итак у нас есть приватный список для хранения актуальных ассетов, у пользователя есть два метода для добавления и удаления ассетов их списка. После добавления в список вызывается наш абстрактный метод Load который и выполняет основную работу по загрузке ассета.
Далее мы напишем врапер для Texture2D на основе нашего базового класса, основная задача которого, как раз загрузка текстуры с указанного имени файла.
Для начала скомпилируйте приложение, чтобы студия создала папки, запустите любой графический редактор, вполне подойдет Paint.NET и создайте пустой графический файл. Сохраните файл под именем test.png в папке в которую у Вас прошла компиляция проекта, не закрывая графического редактора.
Теперь запустите приложение, переключитесь в графический редактор, измените рисунок, не забудьте сохранить, при переключении обратно в приложение Вы должны увидеть Ваши изменения.
P.S. Данная функциональность была реализована в проекте XNA Content Engine (XCE) но работала на основе событий таймера.