{"id":482545,"date":"2026-06-05T14:13:06","date_gmt":"2026-06-05T14:13:06","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=482545"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=482545","title":{"rendered":"\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c AdaEngine 0.1.0 \u2014 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430 Swift"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b6e\/047\/3f9\/b6e0473f91c09fa90455273353d49604.png\" alt=\"\u0420\u0430\u0431\u043e\u0447\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u043e AdaEditor\" title=\"\" width=\"993\" height=\"336\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b6e\/047\/3f9\/b6e0473f91c09fa90455273353d49604.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b6e\/047\/3f9\/b6e0473f91c09fa90455273353d49604.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<div class=\"floating-image\">\n<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u044f \u0440\u0430\u0434 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c <strong>AdaEngine 0.1.0<\/strong>: \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Swift.<\/p>\n<\/div>\n<p>AdaEngine \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0434\u0435\u0438: Swift \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440, \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043e\u0444\u0442\u0430 \u2014 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c Apple. Swift \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u0435\u043d, \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d, \u0431\u044b\u0441\u0442\u0440 \u0438 \u0443\u0434\u043e\u0431\u0435\u043d \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438. AdaEngine \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u044d\u0442\u0438 \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438\u0433\u0440 \u0447\u0435\u0440\u0435\u0437 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a, data-driven \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0449\u0443\u0449\u0430\u044e\u0442\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u043b\u044f Swift-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<p>AdaEngine \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 GitHub \u043f\u043e\u0434 <a href=\"https:\/\/github.com\/AdaEngine\/AdaEngine\" rel=\"noopener noreferrer nofollow\">\u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MIT<\/a>. \u042d\u0442\u043e\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 \u0432\u0441\u0435 \u0435\u0449\u0435 \u0440\u0430\u043d\u043d\u0438\u0439, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0440\u0443\u0431\u0435\u0436: \u0434\u0432\u0438\u0436\u043e\u043a \u0443\u043c\u0435\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u0430, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0446\u0438\u043a\u043b \u043d\u0430 ECS, \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 UI, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0430\u0441\u0441\u0435\u0442\u044b \u0438 \u0441\u0446\u0435\u043d\u044b, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0437\u0432\u0443\u043a, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0432\u043e\u0434, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0444\u0438\u0437\u0438\u043a\u0443 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0434\u0432\u0438\u0436\u043a\u0430.<\/p>\n<p>\u26a0\ufe0f <em> \u0420\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437 AdaEngine 0.1.0 \u2014 \u0440\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437. API \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f, \u0447\u0430\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0435\u0449\u0435 \u0440\u0430\u0441\u0442\u0435\u0442, \u0430 \u0448\u0435\u0440\u043e\u0445\u043e\u0432\u0430\u0442\u043e\u0441\u0442\u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b. \u042f \u043f\u043e\u043a\u0430 \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0445 production-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0435\u0441\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043c\u043e\u0447\u044c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a.<\/em><\/p>\n<p>\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a <a href=\"https:\/\/adaengine.org\/adaengine-docs\/tutorials\/adaengine\/\" rel=\"noopener noreferrer nofollow\">\u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430\u043c<\/a> \u0438\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c <a href=\"https:\/\/github.com\/AdaEngine\/AdaEngine\" rel=\"noopener noreferrer nofollow\">\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub<\/a>.<\/p>\n<p>\ud83d\udcd6 <em>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u044e \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e AdaEngine \u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0437 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0434\u0432\u0438\u0436\u043a\u043e\u043c.<\/em><\/p>\n<h3>\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AdaEngine?<\/h3>\n<p>AdaEngine \u2014 data-driven \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Swift. \u0415\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0446\u0435\u043b\u0438:<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430<\/strong>: \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0433\u0438\u0431\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u044b\u0442\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/strong>: \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0432\u0438\u0436\u043a\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e.<\/p>\n<\/li>\n<li>\n<p><strong>Data-driven \u043f\u043e\u0434\u0445\u043e\u0434<\/strong>: \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 AdaEngine \u043b\u0435\u0436\u0438\u0442 Entity Component System.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f<\/strong>: \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c<\/strong>: \u043f\u0435\u0440\u0432\u044b\u0439 \u0444\u043e\u043a\u0443\u0441 \u2014 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 2D workflow, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 3D \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0443<\/strong>: \u0441\u0435\u0439\u0447\u0430\u0441 AdaEngine \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b Apple \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0434\u0432\u0438\u0436\u0435\u0442\u0441\u044f \u043a \u0431\u043e\u043b\u0435\u0435 \u0448\u0438\u0440\u043e\u043a\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f Windows, Linux, Android \u0438 WebAssembly\/WebGPU.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p><strong>\u0421\u043f\u0440\u0430\u0439\u0442\u044b<\/strong>: \u0440\u0435\u043d\u0434\u0435\u0440 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0441 batching; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, sprite sheets \u0438 \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0446\u0435\u043d\u044b<\/strong>: \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 ECS-\u043c\u0438\u0440\u043e\u0432 \u0438\u0437 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0446\u0435\u043d.<\/p>\n<\/li>\n<li>\n<p><strong>Tilemaps<\/strong>: \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/ldtk.io\" rel=\"noopener noreferrer nofollow\">LDtk<\/a> \u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 API.<\/p>\n<\/li>\n<li>\n<p><strong>2D-\u0444\u0438\u0437\u0438\u043a\u0430<\/strong>: \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0430 \u0431\u0430\u0437\u0435 <a href=\"https:\/\/box2d.io\" rel=\"noopener noreferrer nofollow\">Box2D v3<\/a>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0441\u0441\u0435\u0442\u044b<\/strong>: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0430\u0441\u0441\u0435\u0442\u043e\u0432, async-\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 handles \u0434\u043b\u044f \u0430\u0441\u0441\u0435\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>Hot asset reloading<\/strong>: \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0445 \u0430\u0441\u0441\u0435\u0442\u043e\u0432 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u0410\u0443\u0434\u0438\u043e<\/strong>: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043b\u0430\u0433\u0438\u043d\u044b<\/strong>: \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u0430\u0443\u0434\u0438\u043e, \u0432\u0432\u043e\u0434, UI, \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0444\u0438\u0437\u0438\u043a\u0430, \u0441\u0446\u0435\u043d\u044b, \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0438 observation<\/strong>: \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0433\u0440\u044b \u0447\u0435\u0440\u0435\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438\u043b\u0438 ECS-style frame events.<\/p>\n<\/li>\n<li>\n<p><strong>Parent\/child-\u0441\u0432\u044f\u0437\u0438<\/strong>: \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435 transform \u0447\u0435\u0440\u0435\u0437 \u043d\u0438\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e render backends<\/strong>: Metal \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 Apple \u0438 WebGPU\/Dawn \u0442\u0430\u043c, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p><strong>Render graphs<\/strong>: \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u043c, \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>AdaUI<\/strong>: UI \u0434\u043b\u044f \u0438\u0433\u0440 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 API, \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c SwiftUI.<\/p>\n<\/li>\n<li>\n<p><strong>\u0413\u0435\u0439\u043c\u043f\u0430\u0434\u044b<\/strong>: \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430\u043c \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440\u044b<\/strong>: \u0440\u0430\u0441\u0442\u0443\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0435\u043c\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0439\u0442\u043e\u0432, UI, \u0432\u0432\u043e\u0434\u0430, \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0441\u0446\u0435\u043d, tilemaps \u0438 3D.<\/p>\n<\/li>\n<\/ul>\n<h3>Swift-native \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f AdaEngine \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442 \u0441 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c \u0442\u0435\u043c, \u043a\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f SwiftUI:<\/p>\n<pre><code class=\"swift\">import AdaEngine@mainstruct AdaApp: App {    var body: some AppScene {        DefaultAppWindow()            .windowMode(.windowed)            .windowTitle(\"Ada App\")    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u0432\u0438\u0436\u043a\u0430.<\/p>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0438\u044f \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u0430\u0443\u0434\u0438\u043e, \u0432\u0432\u043e\u0434, \u0441\u043e\u0431\u044b\u0442\u0438\u044f, UI, \u0444\u0438\u0437\u0438\u043a\u0430, \u0441\u0446\u0435\u043d\u044b, \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0445 defaults \u0438\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u0438\u0439 runtime, \u0432\u044b\u0431\u0440\u0430\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.<\/p>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaapp\/emptywindow\" rel=\"noopener noreferrer nofollow\"><code>EmptyWindow<\/code><\/a> \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e:<\/p>\n<pre><code class=\"swift\">import AdaEngine@mainstruct AdaApp: App {    var body: some AppScene {        EmptyWindow()            .addPlugins(DefaultPlugins())            .windowMode(.windowed)            .windowTitle(\"Ada App\")    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaengine\/defaultplugins\/\" rel=\"noopener noreferrer nofollow\"><code>DefaultPlugins<\/code><\/a> \u2014 \u043d\u0430\u0431\u043e\u0440, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u0435\u043d \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u0438\u0439 runtime, \u0447\u0430\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaengine\/defaultplugins\/disable(_:)\" rel=\"noopener noreferrer nofollow\"><code>disable(_:)<\/code><\/a>.<\/p>\n<h3>Entity Component System<\/h3>\n<p>\u0421\u0435\u0440\u0434\u0446\u0435 AdaEngine \u2014 ECS-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u041e\u043d \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d \u0434\u0432\u0438\u0436\u043a\u0430\u043c\u0438 \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438 \u0432\u0440\u043e\u0434\u0435 Bevy \u0438 RealityKit, \u043d\u043e \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u0449\u0443\u0449\u0430\u0442\u044c\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 Swift.<\/p>\n<p>\u0412 Entity Component System:<\/p>\n<ul>\n<li>\n<p><strong>Entities<\/strong> \u2014 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>Components<\/strong> \u2014 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c.<\/p>\n<\/li>\n<li>\n<p><strong>Systems<\/strong> \u2014 \u043b\u043e\u0433\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>Resources<\/strong> \u2014 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u044f \u043c\u0438\u0440\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u0442\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u0415\u0449\u0435 \u043e\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0433\u0440\u0443 \u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439.<\/p>\n<p>AdaECS \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 Swift-\u0442\u0438\u043f\u044b \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c boilerplate:<\/p>\n<pre><code class=\"swift\">import AdaEngine@Componentstruct Position {    var value: Float}@Componentstruct Velocity {    var value: Float}@Systemfunc Movement(    _ query: Query&lt;        Ref&lt;Position&gt;, \/\/ read-write access        Velocity       \/\/ read-only access    &gt;) {    query.forEach { position, velocity in        position.value += velocity.value    }}struct ExamplePlugin: Plugin {    func setup(in app: AppWorlds) {        app.spawn {            Position(value: 0)            Velocity(value: 1)        }        app.spawn {            Position(value: 1)            Velocity(value: 2)        }        app.addSystem(MovementSystem.self, on: .update)    }}@mainstruct AdaApp: App {    var body: some AppScene {        DefaultAppWindow()            .addPlugins(ExamplePlugin())    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441 <code>@System<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0437\u0430 \u0432\u0430\u0441. \u0412\u044b \u043f\u0438\u0448\u0435\u0442\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u043a\u0430\u043a Swift-\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 AdaEngine \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0435 \u0432 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e ECS-\u0441\u0438\u0441\u0442\u0435\u043c\u0443.<\/p>\n<h4>Queries<\/h4>\n<p>Queries \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438\u0437 \u043c\u0438\u0440\u0430:<\/p>\n<pre><code class=\"swift\">@Systemfunc Movement(_ query: Query&lt;Entity, Transform&gt;) {    query.forEach { entity, transform in        \/\/ Iterate over every entity with a Transform.    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Filter queries<\/h4>\n<p>\u0424\u0438\u043b\u044c\u0442\u0440\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044e\u0442 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439:<\/p>\n<pre><code class=\"swift\">@Systemfunc PlayerMovement(    _ query: FilterQuery&lt;Entity, Transform, With&lt;Player&gt;&gt;) {    query.forEach { entity, transform in        \/\/ Iterate only over entities that also have Player.    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Change detection<\/h4>\n<p>Change detection \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435:<\/p>\n<pre><code class=\"swift\">@Systemfunc EnemyHealthBar(    _ query: FilterQuery&lt;Enemy, Changed&lt;Health&gt;&gt;) {    query.forEach { enemy in        \/\/ Run when Health has been added or changed.    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Resources<\/h4>\n<p>Resources \u0445\u0440\u0430\u043d\u044f\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u044f \u043c\u0438\u0440\u0430:<\/p>\n<pre><code class=\"swift\">struct GameScore: Resource {    var score: Int    var bulletFireCount: Int}world.insertResource(GameScore(score: 0, bulletFireCount: 0))@Systemfunc UpdateScore(score: ResMut&lt;GameScore&gt;) {    score.score += 1}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Delta time \u0442\u043e\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u0430\u043a resource:<\/p>\n<pre><code class=\"swift\">@Systemfunc Movement(    time: Res&lt;DeltaTime&gt;,    query: Query&lt;Ref&lt;Position&gt;&gt;) {    query.forEach {        $0.value += 20 * time.deltaTime    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Commands<\/h4>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043b\u0438\u0431\u043e \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaecs\/commands\" rel=\"noopener noreferrer nofollow\"><code>Commands<\/code><\/a>. \u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0447\u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c.<\/p>\n<pre><code class=\"swift\">@Systemfunc GameStartup(_ commands: Commands) {    commands.spawn(\"Player\") {        Player()        Transform()    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Local values<\/h4>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u043e\u0433\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaecs\/local\" rel=\"noopener noreferrer nofollow\"><code>Local<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">@Systemfunc UpdateData(isUpdated: Local&lt;Bool&gt; = false) {    if !isUpdated.wrappedValue {        \/\/ Perform one-time work.        isUpdated.wrappedValue = true    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Struct systems<\/h4>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f AdaECS \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 struct-based \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaecs\/plainsystem(dependencies:)\" rel=\"noopener noreferrer nofollow\"><code>@PlainSystem<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">@PlainSystem(dependencies: [    .after(EnemyMovement.self),    .before(PhysicsSystem.self)])struct MovementSystem {    @Query&lt;Player, Transform&gt;    private var playerQuery    init(world: World) {}    func update(context: UpdateContext) {        playerQuery.forEach {            \/\/ Update player movement here.        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Schedulers<\/h4>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432 schedulers. \u0412 AdaEngine \u0435\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432\u044b\u0435 \u0441\u0442\u0430\u0434\u0438\u0438: startup, pre-update, update, fixed update \u0438 \u0434\u0440\u0443\u0433\u0438\u0435:<\/p>\n<pre><code class=\"swift\">world    .addSystem(StartupSystem.self, on: .startup)    .addSystem(MovementSystem.self, on: .fixedUpdate)    .addSystem(UpdateEnemySystem.self, on: .preUpdate)    .addSystem(UpdateScoreSystem.self, on: .update)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><code>.startup<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 schedulers, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u0435 \u043d\u0443\u0436\u043d\u0430 \u0441\u0432\u043e\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u26a0\ufe0f \u0420\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437 \u0411\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c. \u0415\u0441\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0442\u043e\u043c \u0436\u0435 scheduler, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0430\u0441\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h4>Bundles<\/h4>\n<p>Bundles \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0434\u043d\u0443 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u041c\u0430\u043a\u0440\u043e\u0441 <code>@Bundle<\/code> \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434, \u043d\u0443\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 bundle \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:<\/p>\n<pre><code class=\"swift\">@Bundlestruct EnemyBundle {    let enemy = Enemy()    let transform: Transform    let health: Health}world.spawn(    \"Enemy\",    bundle: EnemyBundle(        transform: Transform(),        health: Health(30)    ))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Scriptable objects<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0447\u0430\u0441\u0442\u0438 gameplay-\u043a\u043e\u0434\u0430 \u0432\u0430\u043c \u0431\u043b\u0438\u0436\u0435 Unity-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 workflow, AdaEngine \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adascene\/scriptableobject\" rel=\"noopener noreferrer nofollow\"><code>ScriptableObject<\/code><\/a> \u0438 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adascene\/scriptablecomponents\" rel=\"noopener noreferrer nofollow\"><code>ScriptableComponents<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">final class Player: ScriptableObject {    func update(_ deltaTime: TimeInterval) {        if input.isKeyPressed(.w) {            \/\/ Move player.        }    }}world.spawn(\"Player\") {    ScriptableComponents(        components: [            Player()        ]    )}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 object-style escape hatch, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u0432\u0438\u0436\u043e\u043a \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f ECS-first.<\/p>\n<h3>AdaUI<\/h3>\n<p>AdaEngine \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 UI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a AdaUI. \u041e\u043d \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d SwiftUI \u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d \u043a\u0430\u043a \u043d\u0430 \u0438\u0433\u0440\u044b, \u0442\u0430\u043a \u0438 \u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0432 \u0434\u0443\u0445\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432.<\/p>\n<p>SwiftUI \u043f\u043e\u043a\u0430\u0437\u0430\u043b, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u0435\u043a\u043b\u0430\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0439 UI. AdaUI \u043f\u0440\u0438\u043d\u043e\u0441\u0438\u0442 \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u0441\u0442\u0438\u043b\u044c \u0432\u043d\u0443\u0442\u0440\u044c \u0434\u0432\u0438\u0436\u043a\u0430: UI-\u043a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u043d\u0430 Swift \u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0446\u0435\u043d\u044b AdaEngine.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f2\/a44\/358\/6f2a44358794c99a4c32a373f8af2232.jpg\" alt=\"\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f \u0441\u0442\u0435\u043a\u0430 media cards\" title=\"\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f \u0441\u0442\u0435\u043a\u0430 \u043a\u0430\u0440\u0442\u043e\u0447\u0435\u043a media review.\" width=\"1280\" height=\"853\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/6f2\/a44\/358\/6f2a44358794c99a4c32a373f8af2232.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/6f2\/a44\/358\/6f2a44358794c99a4c32a373f8af2232.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f \u0441\u0442\u0435\u043a\u0430 \u043a\u0430\u0440\u0442\u043e\u0447\u0435\u043a media review.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/86a\/d9a\/40d\/86ad9a40d7e72abe9e5131419609935e.jpg\" alt=\"\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f chat composer shell\" title=\"\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0438 chat composer.\" width=\"1280\" height=\"868\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/86a\/d9a\/40d\/86ad9a40d7e72abe9e5131419609935e.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/86a\/d9a\/40d\/86ad9a40d7e72abe9e5131419609935e.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u0435 layout \u0432 AdaUI \u0438 SwiftUI \u0434\u043b\u044f \u043e\u0431\u043e\u043b\u043e\u0447\u043a\u0438 chat composer.<\/figcaption><\/div>\n<\/figure>\n<h4>Views<\/h4>\n<p>View \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaui\/view\" rel=\"noopener noreferrer nofollow\"><code>View<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">struct GameOverView: View {    var body: some View {        Text(\"Game Over\")    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Layout<\/h4>\n<p>\u0412 AdaUI \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0435 stack layout primitives:<\/p>\n<pre><code class=\"swift\">struct GameOverView: View {    var body: some View {        VStack(spacing: 20) {            Text(\"Game Over\")            Text(\"Try again\")        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Interactive elements<\/h4>\n<p>\u041a\u043d\u043e\u043f\u043a\u0438 \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0435 controls \u043c\u043e\u0436\u043d\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u0430\u0442\u044c \u0432 \u0442\u043e\u043c \u0436\u0435 \u0441\u0442\u0438\u043b\u0435:<\/p>\n<pre><code class=\"swift\">struct MenuView: View {    var body: some View {        Button(\"Start Game\") {            \/\/ Start game.        }        Button(action: {            \/\/ Open settings.        }, label: {            Text(\"Settings\")                .foregroundColor(.red)        })    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Modifiers<\/h4>\n<p>Modifiers \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442 \u0441\u0442\u0438\u043b\u044c \u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"swift\">struct GameOverView: View {    var body: some View {        VStack(spacing: 20) {            Text(\"Game Over\")                .font(.system(size: 50))                .foregroundColor(.red)        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>State and bindings<\/h4>\n<p>Views \u043c\u043e\u0433\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438:<\/p>\n<pre><code class=\"swift\">struct GameOverView: View {    @State private var isDead = false    var body: some View {        VStack(spacing: 20) {            if isDead {                Text(\"Game Over\")                    .font(.system(size: 50))                    .foregroundColor(.red)            }        }        .onEvent(YourGameEvent.UserDied) {            self.isDead = true        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Bindings \u043f\u0435\u0440\u0435\u0434\u0430\u044e\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 views:<\/p>\n<pre><code class=\"swift\">struct ParentView: View {    @State private var isDead = false    var body: some View {        SubView(isDead: $isDead)    }}struct SubView: View {    @Binding var isDead: Bool    var body: some View {        if isDead {            Text(\"Game Over\")        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Attaching UI to an entity<\/h4>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c view \u0432 \u043c\u0438\u0440\u0435, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u0435 \u0435\u0433\u043e \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaui\/uicomponent\" rel=\"noopener noreferrer nofollow\"><code>UIComponent<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">let gameOverView = GameOverView()world.spawn(\"GameOverView\") {    UIComponent(view: gameOverView)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Environment access<\/h4>\n<p>AdaUI views \u043c\u043e\u0433\u0443\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0438\u0437 environment. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, view, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0439 \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a ECS-\u043c\u0438\u0440\u0443:<\/p>\n<pre><code class=\"swift\">struct DebugView: View {    @Environment(\\.world)    private var world    var body: some View {        Button(\"Spawn Enemy\") {            world.spawn(\"Enemy\", bundle: EnemyBundle())        }    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Images<\/h4>\n<p>Images \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u044f\u043c\u043e \u0432 UI:<\/p>\n<pre><code class=\"swift\">struct UserAvatarView: View {    var body: some View {        Image(\"@res:\/\/avatar.png\")    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>AdaUI \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432\u0430\u0436\u0435\u043d \u0434\u043b\u044f \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e AdaEngine, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u043f\u043e\u0432\u0435\u0440\u0445 \u0442\u043e\u0439 \u0436\u0435 UI-\u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0433\u0440\u044b.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e2\/fc0\/59b\/2e2fc059b0ba8ddc1417b4d2f157f2c2.png\" alt=\"UI AdaEditor\" title=\"\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u0442\u043e\u0439 \u0436\u0435 \u043e\u0441\u043d\u043e\u0432\u044b AdaUI, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0438\u0433\u0440\u0430\u043c \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c.\" width=\"3680\" height=\"2392\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/2e2\/fc0\/59b\/2e2fc059b0ba8ddc1417b4d2f157f2c2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/2e2\/fc0\/59b\/2e2fc059b0ba8ddc1417b4d2f157f2c2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u0442\u043e\u0439 \u0436\u0435 \u043e\u0441\u043d\u043e\u0432\u044b AdaUI, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u0438\u0433\u0440\u0430\u043c \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c.<\/figcaption><\/div>\n<\/figure>\n<h3>2D-\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438<\/h3>\n<p>AdaEngine 0.1.0 \u0441\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u0440\u0435\u043f\u043a\u043e\u0439 2D-\u043e\u0441\u043d\u043e\u0432\u044b.<\/p>\n<h4>Sprites<\/h4>\n<p>\u0421\u043f\u0440\u0430\u0439\u0442\u044b \u2014 \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u0441\u0442\u0440\u043e\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u0431\u043b\u043e\u043a \u0434\u043b\u044f \u043c\u043d\u043e\u0433\u0438\u0445 2D-\u0438\u0433\u0440. AdaEngine \u0443\u043c\u0435\u0435\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438\u0437 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adarender\/texture2d\" rel=\"noopener noreferrer nofollow\"><code>Texture2D<\/code><\/a> \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 texture resources:<\/p>\n<pre><code class=\"swift\">let texture = try await AssetsManager.load(Texture2D.self, at: \"@res:\/\/sprite.png\")world.spawn {    Sprite(texture: texture)    Transform()}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Texture atlases and sprite sheets<\/h4>\n<p>Texture atlases \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u0438, tile sets \u0438 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430:<\/p>\n<pre><code class=\"swift\">let image = try await AssetsManager.load(Image.self, at: \"@res:\/\/characters.png\")let textureAtlas = TextureAtlas(from: image, size: Vector2(16, 16))world.spawn {    Sprite(        texture: textureAtlas[0, 1],        size: Size(width: 16, height: 16)    )    Transform()}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0441\u043f\u0440\u0430\u0439\u0442\u0430 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d, AdaEngine \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u0438\u0437 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b.<\/p>\n<h4>Tilemaps<\/h4>\n<p>\u0412 AdaEngine \u0435\u0441\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c <code>AdaTilemap<\/code>. \u0412\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0434\u0435\u043c\u043e \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0442 \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b tilemap, \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 tilemap \u043d\u0430 \u0431\u0430\u0437\u0435 LDtk. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0443\u0440\u043e\u0432\u043d\u0438, \u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u0432 ECS-\u043c\u0438\u0440.<\/p>\n<p>\u0426\u0435\u043b\u044c \u2014 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u043d\u044b\u0435 2D workflows: \u0440\u0438\u0441\u043e\u0432\u0430\u0442\u044c \u0443\u0440\u043e\u0432\u043d\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438\u0445 \u043a\u0430\u043a \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c \u0444\u0438\u0437\u0438\u043a\u0443 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0438\u0442\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0d5\/7e9\/b3e\/0d57e9b3e0dcdab0e3dc01fbfe49531c.png\" alt=\"\u0414\u0435\u043c\u043e tilemap\" title=\"\u0421\u0446\u0435\u043d\u0430 tilemap, \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0435\u043d\u043d\u0430\u044f AdaEngine.\" width=\"1824\" height=\"1480\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0d5\/7e9\/b3e\/0d57e9b3e0dcdab0e3dc01fbfe49531c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0d5\/7e9\/b3e\/0d57e9b3e0dcdab0e3dc01fbfe49531c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u0446\u0435\u043d\u0430 tilemap, \u043e\u0442\u0440\u0435\u043d\u0434\u0435\u0440\u0435\u043d\u043d\u0430\u044f AdaEngine.<\/figcaption><\/div>\n<\/figure>\n<h4>2D physics<\/h4>\n<p>AdaEngine \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 <code>AdaPhysics<\/code> \u043d\u0430 \u0431\u0430\u0437\u0435 Box2D. \u041c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u044f\u0442\u044c collision components \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c collision events \u0447\u0435\u0440\u0435\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<p>\u0424\u0438\u0437\u0438\u043a\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 ECS-\u043c\u0438\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 gameplay-\u043a\u043e\u0434 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0442\u044c transforms, sprites, collision components \u0438 systems \u0432 \u043e\u0434\u043d\u043e\u0439 data-driven \u043c\u043e\u0434\u0435\u043b\u0438.<\/p>\n<h3>Scenes<\/h3>\n<p>\u0421\u0446\u0435\u043d\u0430 \u2014 \u044d\u0442\u043e \u043d\u0430\u0431\u043e\u0440 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0438 \u0437\u0430\u0441\u043f\u0430\u0432\u043d\u0438\u0442\u044c \u0432 \u043c\u0438\u0440.<\/p>\n<p>\u041e \u0441\u0446\u0435\u043d\u0435 \u043c\u043e\u0436\u043d\u043e \u0434\u0443\u043c\u0430\u0442\u044c \u043a\u0430\u043a \u043e prefab \u0438\u043b\u0438 \u0444\u0430\u0439\u043b\u0435 \u0443\u0440\u043e\u0432\u043d\u044f: \u043e\u043d\u0430 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0447\u0430\u0441\u0442\u044c \u0438\u0433\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438.<\/p>\n<h4>Scene files<\/h4>\n<p>\u0421\u0446\u0435\u043d\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0439 YAML. \u0424\u0430\u0439\u043b \u0441\u0446\u0435\u043d\u044b \u043c\u043e\u0436\u0435\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438, \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, transforms, sprites, physics components \u0438 resources:<\/p>\n<pre><code class=\"yaml\">version: 1.0.0scene: Sceneworld:  entities:  - name: Ground    id: 122210699653662020    components:      AdaSprite.Sprite:        tintColor:          red: 1.0          green: 1.0          blue: 1.0          alpha: 1.0        flipX: false        flipY: false      AdaTransform.Transform:        rotation:          x: 0.0          y: 0.0          z: 0.0          w: 1.0        scale:          x: 3.0          y: 0.19          z: 0.19        position:          x: 0.0          y: -1.0          z: 0.0      AdaPhysics.Collision2DComponent:        shapes:        - fixture:            box:              _0:                halfWidth: 0.5                halfHeight: 0.5                offset:                  x: 0.0                  y: 0.0        mode:          default: {}  resources: {}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Loading scenes<\/h4>\n<p>\u0421\u0446\u0435\u043d\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0430\u0441\u0441\u0435\u0442\u0430\u043c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 asset system:<\/p>\n<pre><code class=\"swift\">let scene = try await AssetsManager.load(Scene.self, at: \"@res:\/\/game_scene.ascn\")world.spawn(\"Spawned scene\") {    DynamicScene(scene: scene)}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u0441\u043f\u0430\u0432\u043d\u0435\u043d\u043d\u0430\u044f \u0441\u0446\u0435\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u044b \u043f\u043e\u0434 parent entity.<\/p>\n<h4>Hot reloading scenes<\/h4>\n<p>Hot reloading \u0441\u0446\u0435\u043d \u2014 \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438. \u041a\u043e\u0433\u0434\u0430 \u0444\u0430\u0439\u043b \u0441\u0446\u0435\u043d\u044b \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f, AdaEngine \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u0442\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a \u0443\u0436\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0439 \u0441\u0446\u0435\u043d\u0435 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438 \u043f\u043e\u043b\u043d\u043e\u0439 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438. \u042d\u0442\u043e \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u0443\u0441\u043a\u043e\u0440\u044f\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 gameplay.<\/p>\n<p>\ud83d\udcd6 Hot reload \u2014 \u0440\u0430\u043d\u043d\u044f\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c, \u043d\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0435: \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435, \u0441\u0440\u0430\u0437\u0443 \u0432\u0438\u0434\u0435\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0438 \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u0444\u043e\u043a\u0443\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u043d\u0430 \u0438\u0433\u0440\u0435, \u0430 \u043d\u0435 \u043d\u0430 \u0446\u0438\u043a\u043b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438.<\/p>\n<h3>Events<\/h3>\n<p>\u0418\u0433\u0440\u0430\u043c \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u043f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u0449\u0430\u0442\u044c\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f: \u043d\u0430\u0447\u0438\u043d\u0430\u044e\u0442\u0441\u044f \u0441\u0442\u043e\u043b\u043a\u043d\u043e\u0432\u0435\u043d\u0438\u044f, \u043d\u0430\u0436\u0438\u043c\u0430\u044e\u0442\u0441\u044f \u043a\u043d\u043e\u043f\u043a\u0438, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f UI, \u043f\u043e\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u0440\u0430\u0433\u0438, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0438\u0433\u0440\u043e\u043a\u0438, \u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043d\u0430 \u044d\u0442\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c.<\/p>\n<p>AdaEngine \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 event-style messaging, \u0438 ECS frame events.<\/p>\n<h4>EventManager<\/h4>\n<p>\u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0434\u043f\u0438\u0441\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c cancellable token:<\/p>\n<pre><code class=\"swift\">let cancellable = world.subscribe(    on: CollisionEvents.Began.self) { payload in    \/\/ Handle collision.}world.eventManager.sendEvent(SomeEvent())\/\/ Or send globally:EventManager.default.sendEvent(SomeEvent())<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>ECS events<\/h4>\n<p>\u0414\u043b\u044f ECS-native workflows AdaEngine \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>Events<\/code> \u0438 <code>EventSender<\/code>:<\/p>\n<pre><code class=\"swift\">@Systemfunc HostConnection(_ events: Events&lt;OnConnect&gt;) {    for event in events {        print(\"User connected\", event.userId)    }}@Systemfunc ConnectionUpdate(_ sender: EventSender&lt;OnConnect&gt;) {    sender(OnConnect(userId: \"player#123\"))}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\ud83d\udcd6 ECS events \u2014 \u044d\u0442\u043e frame events: \u043e\u043d\u0438 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u0435\u0447\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043a\u0430\u0434\u0440\u0430.<\/p>\n<h3>Assets<\/h3>\n<p>Asset system \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435. \u0410\u0441\u0441\u0435\u0442\u044b \u0441\u0441\u044b\u043b\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 handles, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c hot reloading.<\/p>\n<p>\u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<pre><code class=\"swift\">let texture: AssetHandle&lt;Texture2D&gt; = try await AssetsManager.load(    Texture2D.self,    at: \"@res:\/\/my_texture.png\")<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u0435\u0444\u0438\u043a\u0441 <code>@res:\/\/<\/code> \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e AdaEngine \u0438\u0449\u0435\u0442 \u043f\u0430\u043f\u043a\u0443 <code>Assets<\/code> \u0438\u043b\u0438 <code>Resources<\/code> \u0432 \u0432\u0430\u0448\u0435\u043c target. \u0422\u0430\u043a\u0436\u0435 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u0434\u0430\u0442\u044c \u0432\u0440\u0443\u0447\u043d\u0443\u044e.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0438\u0437 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e bundle:<\/p>\n<pre><code class=\"swift\">let texture: AssetHandle&lt;Texture2D&gt; = try await AssetsManager.load(    Texture2D.self,    at: \"my_texture.png\",    from: Foundation.Bundle(path: \"\"))<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c hot reloading \u0434\u043b\u044f \u0430\u0441\u0441\u0435\u0442\u0430, \u043f\u0435\u0440\u0435\u0434\u0430\u0439\u0442\u0435 <code>handleChanges: true<\/code>:<\/p>\n<pre><code class=\"swift\">let texture: AssetHandle&lt;Texture2D&gt; = try await AssetsManager.load(    Texture2D.self,    at: \"@res:\/\/my_texture.png\",    handleChanges: true)<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h4>Adding a new asset type<\/h4>\n<p>\u041c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0430\u0441\u0441\u0435\u0442\u043e\u0432, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b <a href=\"https:\/\/adaengine.org\/adaengine-docs\/documentation\/adaassets\/asset\" rel=\"noopener noreferrer nofollow\"><code>Asset<\/code><\/a>:<\/p>\n<pre><code class=\"swift\">struct MyAsset: Asset {    init(asset decoder: AssetDecoder) async throws {        \/\/ Decode asset contents.    }    func encodeContents(with encoder: AssetEncoder) async throws {        \/\/ Encode asset contents.    }    static func extensions() -&gt; [String] {        [\"txt\"]    }}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0430\u0441\u0441\u0435\u0442 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0447\u0435\u0440\u0435\u0437 \u0442\u043e\u0442 \u0436\u0435 loading pipeline, \u0447\u0442\u043e \u0438 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, \u0437\u0432\u0443\u043a\u0438, \u0441\u0446\u0435\u043d\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b.<\/p>\n<h3>Audio<\/h3>\n<p>AdaEngine \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043c\u043e\u0434\u0443\u043b\u044c <code>AdaAudio<\/code> \u043d\u0430 \u0431\u0430\u0437\u0435 miniaudio. \u041c\u043e\u0436\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c audio resource \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u0438 \u0435\u0433\u043e \u043e\u0442 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code class=\"swift\">let backgroundSound = try await AssetsManager.load(    AudioResource.self,    at: \"@res:\/\/background.wav\")let player = world.spawn {    Player()}player.prepareAudio(backgroundSound)    .setLoop(true)    .play()<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410\u0443\u0434\u0438\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c, \u0447\u0442\u043e \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043f\u0443\u0442\u044c \u043a spatial sound \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044e, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u043e\u043c\u0443 gameplay.<\/p>\n<h3>Rendering<\/h3>\n<p>\u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0432 AdaEngine \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u0438 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u0412 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u0435 \u0435\u0441\u0442\u044c:<\/p>\n<ul>\n<li>\n<p><code>AdaRender<\/code> \u0434\u043b\u044f render abstractions, \u043a\u0430\u043c\u0435\u0440, \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u0432, meshes, \u0442\u0435\u043a\u0441\u0442\u0443\u0440, render pipelines \u0438 render graphs.<\/p>\n<\/li>\n<li>\n<p><code>AdaSprite<\/code> \u0434\u043b\u044f 2D sprite rendering.<\/p>\n<\/li>\n<li>\n<p><code>AdaCorePipelines<\/code> \u0434\u043b\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0445 rendering pipelines \u0438 shaders.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 Metal \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 Apple.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 WebGPU \u0447\u0435\u0440\u0435\u0437 Dawn\/Swan \u0442\u0430\u043c, \u0433\u0434\u0435 \u043e\u043d\u0430 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u0438 \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u0438 shaders \u0432\u043e\u043a\u0440\u0443\u0433 SPIR-V tooling.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412 \u044d\u0442\u043e\u043c \u0440\u0435\u043b\u0438\u0437\u0435 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u0430 \u0438 \u0434\u043b\u044f 2D-, \u0438 \u0434\u043b\u044f 3D-\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430. \u0421\u0435\u0439\u0447\u0430\u0441 2D-\u043f\u0443\u0442\u044c \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0437\u0440\u0435\u043b\u044b\u0439. 3D \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 \u0432\u043a\u043b\u044e\u0447\u0430\u044f meshes, \u043a\u0430\u043c\u0435\u0440\u044b, \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b \u0438 \u0434\u0435\u043c\u043e \u0441 \u043a\u0443\u0431\u043e\u043c, \u2014 \u043d\u043e \u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u0440\u0430\u0431\u043e\u0442\u044b, \u043f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043e\u0449\u0443\u0449\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u044b\u043c.<\/p>\n<p>Render graphs \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0435\u0433\u043e \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041e\u043d\u0438 \u0434\u0435\u043b\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u044f\u0432\u043d\u043e\u0439 \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0443\u0435\u043c\u043e\u0439, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u043c\u043e\u0447\u044c \u0434\u0432\u0438\u0436\u043a\u0443 \u0432\u044b\u0440\u0430\u0441\u0442\u0438 \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 sprite scenes \u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u044b\u0445 pipelines.<\/p>\n<h3>Platforms and tooling<\/h3>\n<p>AdaEngine \u2014 \u044d\u0442\u043e Swift Package \u043d\u0430 Swift 6.2. \u0421\u0435\u0439\u0447\u0430\u0441 package \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u0442 targets \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c Apple, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a macOS 15, iOS 18, tvOS 18 \u0438 visionOS 2. \u0422\u0430\u043a\u0436\u0435 \u0432 \u043d\u0435\u043c \u0435\u0441\u0442\u044c conditional compilation \u0438 platform backends \u0434\u043b\u044f Linux, Windows, Android, WASI\/WebAssembly, Metal, WebGPU, X11 \u0438 browser runtimes.<\/p>\n<p>\u041d\u0435 \u0432\u0441\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043f\u043e\u043a\u0430 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e \u0437\u0440\u0435\u043b\u044b\u0435. \u041f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b Apple \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0433\u043e\u0442\u043e\u0432\u044b \u043b\u0443\u0447\u0448\u0435 \u0432\u0441\u0435\u0433\u043e, \u0430 Windows, Linux, Android \u0438 Web \u0432\u0445\u043e\u0434\u044f\u0442 \u0432 \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0442\u0430\u043a\u0436\u0435 \u0435\u0441\u0442\u044c SwiftPM-\u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0432\u043a\u043b\u044e\u0447\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>Ada web export plugin,<\/p>\n<\/li>\n<li>\n<p>build tooling, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441 WebGPU\/Tint,<\/p>\n<\/li>\n<li>\n<p>\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 texture atlas,<\/p>\n<\/li>\n<li>\n<p>tooling \u0434\u043b\u044f \u0442\u0440\u0430\u043d\u0441\u043f\u0438\u043b\u044f\u0446\u0438\u0438 shaders,<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 \u0447\u0435\u0440\u0435\u0437 DocC.<\/p>\n<\/li>\n<\/ul>\n<h3>Examples<\/h3>\n<p>\u0412 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u0435\u0441\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0432 <a href=\"https:\/\/github.com\/AdaEngine\/AdaEngine\/tree\/main\/Demos\" rel=\"noopener noreferrer nofollow\"><code>Demos<\/code><\/a>, \u0432\u043a\u043b\u044e\u0447\u0430\u044f:<\/p>\n<ul>\n<li>\n<p>\u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 \u0441\u043f\u0440\u0430\u0439\u0442\u043e\u0432,<\/p>\n<\/li>\n<li>\n<p>many sprites \/ stress examples,<\/p>\n<\/li>\n<li>\n<p>custom materials,<\/p>\n<\/li>\n<li>\n<p>2D lighting,<\/p>\n<\/li>\n<li>\n<p>transparency,<\/p>\n<\/li>\n<li>\n<p>text rendering,<\/p>\n<\/li>\n<li>\n<p>gamepad input,<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0441\u0446\u0435\u043d,<\/p>\n<\/li>\n<li>\n<p>LDtk tilemaps,<\/p>\n<\/li>\n<li>\n<p>scriptable components,<\/p>\n<\/li>\n<li>\n<p>collision events,<\/p>\n<\/li>\n<li>\n<p>UI-\u043f\u0440\u0438\u043c\u0435\u0440\u044b: buttons, text fields, scene views, animated text \u0438 Kanban board,<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u043e\u0441\u0442\u043e\u0439 3D-\u043f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043a\u0443\u0431\u043e\u043c,<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0434\u0435\u043c\u043e \u0432\u0440\u043e\u0434\u0435 Snowman Attacks.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0432\u0430\u0436\u043d\u044b, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442, \u0447\u0442\u043e \u0434\u0432\u0438\u0436\u043e\u043a \u0443\u0436\u0435 \u0443\u043c\u0435\u0435\u0442, \u0430 \u0435\u0449\u0435 \u0441\u043b\u0443\u0436\u0430\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0442\u0435\u0441\u0442\u0430\u043c\u0438 workflows \u0434\u0432\u0438\u0436\u043a\u0430.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4d4\/dcf\/2b3\/4d4dcf2b36a12746941be549033da24f.png\" alt=\"\u0414\u0435\u043c\u043e Duck Hunt\" title=\"\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0434\u0435\u043c\u043e \u0432 \u0441\u0442\u0438\u043b\u0435 Duck Hunt, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 AdaEngine.\" width=\"1280\" height=\"320\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4d4\/dcf\/2b3\/4d4dcf2b36a12746941be549033da24f.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4d4\/dcf\/2b3\/4d4dcf2b36a12746941be549033da24f.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u0434\u0435\u043c\u043e \u0432 \u0441\u0442\u0438\u043b\u0435 Duck Hunt, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0435 \u043d\u0430 AdaEngine.<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/531\/0fb\/548\/5310fb548da83825aa0eacd90f1bb87a.jpeg\" alt=\"\u0414\u0435\u043c\u043e Space Invaders\" title=\"\u0414\u0435\u043c\u043e \u0432 \u0441\u0442\u0438\u043b\u0435 Space Invaders \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 AdaEngine.\" width=\"3456\" height=\"2072\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/531\/0fb\/548\/5310fb548da83825aa0eacd90f1bb87a.jpeg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/531\/0fb\/548\/5310fb548da83825aa0eacd90f1bb87a.jpeg 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0435\u043c\u043e \u0432 \u0441\u0442\u0438\u043b\u0435 Space Invaders \u0438\u0437 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432 AdaEngine.<\/figcaption><\/div>\n<\/figure>\n<h3>\u0417\u0430\u0447\u0435\u043c \u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u043b AdaEngine<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u0433\u0440\u044b \u0431\u044b\u043b\u043e \u043c\u043e\u0435\u0439 \u0434\u0435\u0442\u0441\u043a\u043e\u0439 \u043c\u0435\u0447\u0442\u043e\u0439. \u042f \u043d\u0430\u0447\u0430\u043b \u0443\u0447\u0438\u0442\u044c Java, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0445\u043e\u0442\u0435\u043b \u0434\u0435\u043b\u0430\u0442\u044c \u043c\u043e\u0434\u044b \u0434\u043b\u044f Minecraft. \u041f\u043e\u0437\u0436\u0435 \u044f \u0441\u0442\u0430\u043b iOS-\u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043e\u043c, \u043d\u043e \u043c\u0435\u0447\u0442\u0430 \u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u044b \u043d\u0438\u043a\u0443\u0434\u0430 \u043d\u0435 \u0438\u0441\u0447\u0435\u0437\u043b\u0430.<\/p>\n<p>\u042f \u043c\u043d\u043e\u0433\u043e \u0441\u0432\u043e\u0431\u043e\u0434\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438\u0437\u0443\u0447\u0430\u043b Godot, \u043f\u043e\u0433\u0440\u0443\u0436\u0430\u043b\u0441\u044f \u0432 \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e game development \u0438 \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0434\u0432\u0438\u0436\u043a\u0438 \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u044b \u0438\u0437\u043d\u0443\u0442\u0440\u0438. \u042f \u043d\u0430\u0447\u0430\u043b \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0433\u043e Metal-\u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u043b \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u0441\u043b\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043b\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u0434\u043e\u0448\u0435\u043b \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u0440\u0443\u0431\u0435\u0436\u0430: \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0435\u043b\u0438\u0437\u0430 AdaEngine.<\/p>\n<p>\u042f \u043b\u044e\u0431\u043b\u044e open source. \u042f \u043b\u044e\u0431\u043b\u044e Swift. \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u043c\u043d\u043e\u0433\u043e open source Swift-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438 \u043c\u043d\u0435 \u0431\u044b\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Swift \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u043d\u043e \u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u043e\u0433\u043e \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u0434\u0432\u0438\u0436\u043a\u0430.<\/p>\n<p>Swift \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0438\u0442\u044c \u043c\u043d\u043e\u0433\u043e\u0435: value types, protocol-oriented design, macros, structured concurrency, memory safety, \u0441\u0438\u043b\u044c\u043d\u044b\u0439 tooling \u0438 \u043f\u0440\u0438\u044f\u0442\u043d\u044b\u0439 \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441. \u0421\u0430\u043c\u0430\u044f \u0431\u043e\u043b\u044c\u0448\u0430\u044f \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043d\u0435 \u0432 \u044f\u0437\u044b\u043a\u0435, \u0430 \u0432 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0438, \u0447\u0442\u043e Swift \u043f\u0440\u0438\u043d\u0430\u0434\u043b\u0435\u0436\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u043f\u043e\u0434 macOS \u0438 iOS.<\/p>\n<p>\u042f \u043d\u0435 \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u044d\u0442\u043e \u043f\u0440\u0430\u0432\u0434\u0430. Swift \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0447\u0435\u043c-\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u043c. AdaEngine \u2014 \u043c\u043e\u044f \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u043f\u043e\u043c\u043e\u0447\u044c \u044d\u0442\u043e \u0434\u043e\u043a\u0430\u0437\u0430\u0442\u044c.<\/p>\n<h3>\u0427\u0442\u043e \u0434\u0430\u043b\u044c\u0448\u0435?<\/h3>\n<p>AdaEngine 0.1.0 \u2014 \u044d\u0442\u043e \u043d\u0430\u0447\u0430\u043b\u043e, \u0430 \u043d\u0435 \u0444\u0438\u043d\u0438\u0448\u043d\u0430\u044f \u0447\u0435\u0440\u0442\u0430. \u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0444\u0430\u0437\u0430 \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a, \u043f\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043f\u044b\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0441\u0442\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u0441\u0442\u0432\u043e.<\/p>\n<h4>\u0411\u043e\u043b\u044c\u0448\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c<\/h4>\n<p>\u0414\u043e\u043b\u0433\u043e\u0441\u0440\u043e\u0447\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u2014 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c. Swift \u2014 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0438 \u043c\u043e\u0449\u043d\u044b\u0439 \u044f\u0437\u044b\u043a, \u0438 \u044f \u0432\u0435\u0440\u044e, \u0447\u0442\u043e \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u043e\u0439\u0442\u0438 \u0434\u043b\u044f \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438\u0433\u0440.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0430\u044f \u0432\u0430\u0436\u043d\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u043f\u043e \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u043c \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 WebAssembly\/WebGPU, Linux, Android \u0438 \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Windows.<\/p>\n<h4>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440<\/h4>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0433\u0440 \u0445\u043e\u0442\u044f\u0442 \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u043c\u0435\u043d\u044c\u0448\u0435 boilerplate. AdaUI \u0434\u0430\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u0443 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0442\u043e\u0439 \u0436\u0435 UI-\u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0441\u043c\u043e\u0433\u0443\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u0433\u0440\u044b.<\/p>\n<p>\u0421\u043e\u0431\u0440\u0430\u0442\u044c AdaEditor \u043d\u0430 AdaUI \u2014 \u0432\u0430\u0436\u043d\u0430\u044f \u0446\u0435\u043b\u044c: \u044d\u0442\u043e \u0443\u043b\u0443\u0447\u0448\u0438\u0442 UI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a, \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442 tooling \u0434\u0432\u0438\u0436\u043a\u0430 \u0438 \u0441\u0434\u0435\u043b\u0430\u0435\u0442 AdaEngine \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0435\u0435 \u0434\u043b\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0431\u043b\u0438\u0436\u0435 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0435 workflows.<\/p>\n<h4>3D rendering and polish<\/h4>\n<p>2D feature set \u2014 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u0444\u043e\u043a\u0443\u0441 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u043b\u0438\u0437\u0430, \u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 3D \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442 \u0443\u043b\u0443\u0447\u0448\u0430\u0442\u044c\u0441\u044f. \u0420\u0430\u0431\u043e\u0442\u044b \u043c\u043d\u043e\u0433\u043e: \u043b\u0443\u0447\u0448\u0438\u0435 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u044b, \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, MSAA, \u0431\u043e\u043b\u0435\u0435 \u0431\u043e\u0433\u0430\u0442\u044b\u0439 scene tooling, workflows \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0435\u0439 \u0438 \u043c\u043d\u043e\u0433\u043e\u0435 \u0434\u0440\u0443\u0433\u043e\u0435.<\/p>\n<p>\u0414\u0432\u0438\u0436\u043a\u0443 \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u043b\u0438\u0440\u043e\u0432\u043a\u0430 \u0432\u043e \u043c\u043d\u043e\u0433\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445: asset workflows, hot reloading, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c, diagnostics, examples \u0438 \u0434\u0438\u0437\u0430\u0439\u043d API.<\/p>\n<h4>\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0438 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u044b<\/h4>\n<p>API \u0432\u0441\u0435 \u0435\u0449\u0435 \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u0435\u043d, \u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043c\u0435\u0441\u0442\u0430\u043c\u0438 sparse. \u0412 \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0435\u043c \u0431\u0443\u0434\u0443\u0449\u0435\u043c AdaEngine \u043d\u0443\u0436\u043d\u044b \u043d\u043e\u0432\u044b\u0435 \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u044b, \u0431\u043e\u043b\u0435\u0435 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 guides \u0438 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0442 \u043f\u043e\u043b\u043d\u044b\u0435 workflows: \u043e\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043e \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u043c\u0435\u0445\u0430\u043d\u0438\u043a.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u2014 \u043d\u0435 \u043e\u043f\u0446\u0438\u044f. \u042d\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u0434\u0432\u0438\u0436\u043a\u0430.<\/p>\n<h3>\u041f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u043a AdaEngine<\/h3>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u044d\u0442\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0437\u0430\u0433\u043b\u044f\u043d\u0438\u0442\u0435 \u0432 <a href=\"https:\/\/github.com\/AdaEngine\/AdaEngine\" rel=\"noopener noreferrer nofollow\">AdaEngine \u043d\u0430 GitHub<\/a>, \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0439\u0442\u0435 <a href=\"https:\/\/adaengine.org\/adaengine-docs\/tutorials\/adaengine\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0435\u0440\u0438\u044e \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u043e\u0432<\/a>, \u0438\u0437\u0443\u0447\u0438\u0442\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438 \u043f\u0440\u0438\u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0439\u0442\u0435\u0441\u044c \u043a \u043e\u0431\u0441\u0443\u0436\u0434\u0435\u043d\u0438\u044e.<\/p>\n<p>AdaEngine \u0441\u0435\u0439\u0447\u0430\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432\u043e\u043b\u043e\u043d\u0442\u0435\u0440\u0430\u043c\u0438. \u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043c\u043e\u0447\u044c \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u043d\u0430 Swift \u2014 \u043a\u043e\u0434\u043e\u043c, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439, \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u043c\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c, feedback \u043f\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0443 \u0438\u043b\u0438 \u0438\u0434\u0435\u044f\u043c\u0438, \u2014 \u0432\u0430\u043c \u043e\u0447\u0435\u043d\u044c \u0440\u0430\u0434\u044b.<\/p>\n<p>\u042d\u0442\u043e \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u0432\u0435\u0440\u0441\u0438\u044f 0.1.0, \u043d\u043e \u044d\u0442\u043e \u043d\u0430\u0447\u0430\u043b\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u044f \u0434\u0430\u0432\u043d\u043e \u0445\u043e\u0442\u0435\u043b \u043f\u043e\u0441\u0442\u0440\u043e\u0438\u0442\u044c.<\/p>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0433\u0440\u044b \u043d\u0430 Swift.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1044142\/\">https:\/\/habr.com\/ru\/articles\/1044142\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041f\u043e\u0441\u043b\u0435 \u0434\u043e\u043b\u0433\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u044f \u0440\u0430\u0434 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c AdaEngine 0.1.0: \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 Swift.AdaEngine \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u0432\u043e\u043a\u0440\u0443\u0433 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438\u0434\u0435\u0438: Swift \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u0433\u0440, \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u0442\u0432\u043e\u0440\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043e\u0444\u0442\u0430 \u2014 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c Apple. Swift \u0432\u044b\u0440\u0430\u0437\u0438\u0442\u0435\u043b\u0435\u043d, \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u0435\u043d, \u0431\u044b\u0441\u0442\u0440 \u0438 \u0443\u0434\u043e\u0431\u0435\u043d \u0432 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0438. AdaEngine \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u044d\u0442\u0438 \u0441\u0438\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0438\u0433\u0440 \u0447\u0435\u0440\u0435\u0437 \u043c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0439 \u0434\u0432\u0438\u0436\u043e\u043a, data-driven \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0443 \u0438 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0449\u0443\u0449\u0430\u044e\u0442\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0434\u043b\u044f Swift-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.AdaEngine \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043d\u0430 GitHub \u043f\u043e\u0434 \u043b\u0438\u0446\u0435\u043d\u0437\u0438\u0435\u0439 MIT. \u042d\u0442\u043e\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0435\u043b\u0438\u0437 \u0432\u0441\u0435 \u0435\u0449\u0435 \u0440\u0430\u043d\u043d\u0438\u0439, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u044d\u0442\u043e \u0443\u0436\u0435 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0439 \u0440\u0443\u0431\u0435\u0436: \u0434\u0432\u0438\u0436\u043e\u043a \u0443\u043c\u0435\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0442\u044c \u043e\u043a\u043d\u0430, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0446\u0438\u043a\u043b \u043d\u0430 ECS, \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 UI, \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0430\u0441\u0441\u0435\u0442\u044b \u0438 \u0441\u0446\u0435\u043d\u044b, \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u0437\u0432\u0443\u043a, \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0432\u043e\u0434, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0444\u0438\u0437\u0438\u043a\u0443 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0434\u0432\u0438\u0436\u043a\u0430.\u26a0\ufe0f  \u0420\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437 AdaEngine 0.1.0 \u2014 \u0440\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437. API \u0431\u0443\u0434\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f, \u0447\u0430\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u043f\u043e\u043a\u0430 \u043d\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0435\u0449\u0435 \u0440\u0430\u0441\u0442\u0435\u0442, \u0430 \u0448\u0435\u0440\u043e\u0445\u043e\u0432\u0430\u0442\u043e\u0441\u0442\u0438 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b. \u042f \u043f\u043e\u043a\u0430 \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0434\u043b\u044f \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u0445 production-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0435\u0441\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u044b \u043d\u0435 \u0433\u043e\u0442\u043e\u0432\u044b \u043a \u043d\u0435\u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0438 \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043c\u043e\u0447\u044c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0438\u0436\u043e\u043a.\u0415\u0441\u043b\u0438 \u044d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430\u043c \u0438\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043d\u0430 GitHub.\ud83d\udcd6 \u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u044e \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e AdaEngine \u0438 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434. \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438\u0437 \u043a\u043e\u0434\u043e\u0432\u043e\u0439 \u0431\u0430\u0437\u044b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u0434\u0432\u0438\u0436\u043a\u043e\u043c.\u0427\u0442\u043e \u0442\u0430\u043a\u043e\u0435 AdaEngine?AdaEngine \u2014 data-driven \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u0432\u0438\u0436\u043e\u043a \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 Swift. \u0415\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0446\u0435\u043b\u0438:\u041f\u0440\u043e\u0441\u0442\u043e\u0442\u0430: \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u043d\u043e\u0432\u0438\u0447\u043a\u0430\u043c, \u043d\u043e \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0433\u0438\u0431\u043a\u043e \u0434\u043b\u044f \u043e\u043f\u044b\u0442\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439.\u041c\u043e\u0434\u0443\u043b\u044c\u043d\u043e\u0441\u0442\u044c: \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0434\u0432\u0438\u0436\u043a\u0430 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u0442\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u0430\u0448\u0435\u043c\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044e.Data-driven \u043f\u043e\u0434\u0445\u043e\u0434: \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 AdaEngine \u043b\u0435\u0436\u0438\u0442 Entity Component System.\u0411\u044b\u0441\u0442\u0440\u0430\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044f: \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u0431\u044b\u0441\u0442\u0440\u044b\u0435 \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0432\u044f\u0437\u044c.\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u044c: \u043f\u0435\u0440\u0432\u044b\u0439 \u0444\u043e\u043a\u0443\u0441 \u2014 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0439 2D workflow, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 3D \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f.\u041a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0434\u0438\u0437\u0430\u0439\u043d\u0443: \u0441\u0435\u0439\u0447\u0430\u0441 AdaEngine \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b Apple \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0434\u0432\u0438\u0436\u0435\u0442\u0441\u044f \u043a \u0431\u043e\u043b\u0435\u0435 \u0448\u0438\u0440\u043e\u043a\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f Windows, Linux, Android \u0438 WebAssembly\/WebGPU.\u0422\u0435\u043a\u0443\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442:\u0421\u043f\u0440\u0430\u0439\u0442\u044b: \u0440\u0435\u043d\u0434\u0435\u0440 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0442\u0435\u043a\u0441\u0442\u0443\u0440 \u0441 batching; \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b, sprite sheets \u0438 \u0430\u043d\u0438\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u043a\u0441\u0442\u0443\u0440\u044b.\u0421\u0446\u0435\u043d\u044b: \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 ECS-\u043c\u0438\u0440\u043e\u0432 \u0438\u0437 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0441\u0446\u0435\u043d.Tilemaps: \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0443\u0440\u043e\u0432\u043d\u0435\u0439 \u0447\u0435\u0440\u0435\u0437 LDtk \u0438\u043b\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0434\u0440\u0443\u0433\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 API.2D-\u0444\u0438\u0437\u0438\u043a\u0430: \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043d\u0430 \u0431\u0430\u0437\u0435 Box2D v3.\u0410\u0441\u0441\u0435\u0442\u044b: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u0445 \u0430\u0441\u0441\u0435\u0442\u043e\u0432, async-\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 handles \u0434\u043b\u044f \u0430\u0441\u0441\u0435\u0442\u043e\u0432.Hot asset reloading: \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u043d\u044b\u0445 \u0430\u0441\u0441\u0435\u0442\u043e\u0432 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u043e\u0441\u0442\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0442\u043e\u043a\u0435.\u0410\u0443\u0434\u0438\u043e: \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0437\u0432\u0443\u043a\u043e\u0432\u044b\u0445 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c.\u041f\u043b\u0430\u0433\u0438\u043d\u044b: \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u0430\u0443\u0434\u0438\u043e, \u0432\u0432\u043e\u0434, UI, \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0444\u0438\u0437\u0438\u043a\u0430, \u0441\u0446\u0435\u043d\u044b, \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b.\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0438 observation: \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0433\u0440\u044b \u0447\u0435\u0440\u0435\u0437 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438\u043b\u0438 ECS-style frame events.Parent\/child-\u0441\u0432\u044f\u0437\u0438: \u0438\u0435\u0440\u0430\u0440\u0445\u0438\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439 \u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0435 transform \u0447\u0435\u0440\u0435\u0437 \u043d\u0438\u0445.\u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e render backends: Metal \u043d\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445 Apple \u0438 WebGPU\/Dawn \u0442\u0430\u043c, \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u043e.Render graphs: \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u043c, \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0443\u0435\u0442\u0441\u044f \u0440\u0430\u0431\u043e\u0442\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430.AdaUI: UI \u0434\u043b\u044f \u0438\u0433\u0440 \u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0441 API, \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c SwiftUI.\u0413\u0435\u0439\u043c\u043f\u0430\u0434\u044b: \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u044b\u043c \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430\u043c \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445.\u041f\u0440\u0438\u043c\u0435\u0440\u044b: \u0440\u0430\u0441\u0442\u0443\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0435\u043c\u043e \u0434\u043b\u044f \u0441\u043f\u0440\u0430\u0439\u0442\u043e\u0432, UI, \u0432\u0432\u043e\u0434\u0430, \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0441\u0446\u0435\u043d, tilemaps \u0438 3D.Swift-native \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f AdaEngine \u0441\u0442\u0430\u0440\u0442\u0443\u044e\u0442 \u0441 API, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0437\u043d\u0430\u043a\u043e\u043c \u0442\u0435\u043c, \u043a\u0442\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f SwiftUI:import AdaEngine@mainstruct AdaApp: App {    var body: some AppScene {        DefaultAppWindow()            .windowMode(.windowed)            .windowTitle(&#171;Ada App&#187;)    }}\u042d\u0442\u043e\u0433\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u043a\u043d\u043e \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0434\u0432\u0438\u0436\u043a\u0430.\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0444\u0438\u043b\u043e\u0441\u043e\u0444\u0438\u044f \u2014 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u043f\u043b\u0430\u0433\u0438\u043d\u044b. \u0420\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433, \u0430\u0443\u0434\u0438\u043e, \u0432\u0432\u043e\u0434, \u0441\u043e\u0431\u044b\u0442\u0438\u044f, UI, \u0444\u0438\u0437\u0438\u043a\u0430, \u0441\u0446\u0435\u043d\u044b, \u0441\u043f\u0440\u0430\u0439\u0442\u044b \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0430\u0442\u044c \u0441 \u0440\u0430\u0437\u0443\u043c\u043d\u044b\u0445 defaults \u0438\u043b\u0438 \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u0438\u0439 runtime, \u0432\u044b\u0431\u0440\u0430\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438.\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 EmptyWindow \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0439\u0442\u0435 \u043f\u043b\u0430\u0433\u0438\u043d\u044b \u0432\u0440\u0443\u0447\u043d\u0443\u044e:import AdaEngine@mainstruct AdaApp: App {    var body: some AppScene {        EmptyWindow()            .addPlugins(DefaultPlugins())            .windowMode(.windowed)            .windowTitle(&#171;Ada App&#187;)    }}DefaultPlugins \u2014 \u043d\u0430\u0431\u043e\u0440, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041a\u043e\u0433\u0434\u0430 \u043d\u0443\u0436\u0435\u043d \u0431\u043e\u043b\u0435\u0435 \u043b\u0435\u0433\u043a\u0438\u0439 runtime, \u0447\u0430\u0441\u0442\u0438 \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0431\u043e\u0440\u0430 \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 disable(_:).Entity Component System\u0421\u0435\u0440\u0434\u0446\u0435 AdaEngine \u2014 ECS-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u041e\u043d \u0432\u0434\u043e\u0445\u043d\u043e\u0432\u043b\u0435\u043d \u0434\u0432\u0438\u0436\u043a\u0430\u043c\u0438 \u0438 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430\u043c\u0438 \u0432\u0440\u043e\u0434\u0435 Bevy \u0438 RealityKit, \u043d\u043e \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043e\u0449\u0443\u0449\u0430\u0442\u044c\u0441\u044f \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 Swift.\u0412 Entity Component System:Entities \u2014 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b.Components \u2014 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u0440\u0438\u043a\u0440\u0435\u043f\u043b\u0435\u043d\u043d\u044b\u0435 \u043a \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c.Systems \u2014 \u043b\u043e\u0433\u0438\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0447\u0438\u0442\u0430\u0435\u0442 \u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b.Resources \u2014 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u044f \u043c\u0438\u0440\u0430.\u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u0442\u0434\u0435\u043b\u044f\u0435\u0442 \u0438\u0433\u0440\u043e\u0432\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u0415\u0449\u0435 \u043e\u043d \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0433\u0440\u0443 \u043e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u043e \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0441\u0438\u0441\u0442\u0435\u043c \u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439.AdaECS \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 Swift-\u0442\u0438\u043f\u044b \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u043a\u0440\u043e\u0441\u044b, \u0447\u0442\u043e\u0431\u044b \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c boilerplate:import AdaEngine@Componentstruct Position {    var value: Float}@Componentstruct Velocity {    var value: Float}@Systemfunc Movement(    _ query: Query&lt;        Ref&lt;Position&gt;, \/\/ read-write access        Velocity       \/\/ read-only access    &gt;) {    query.forEach { position, velocity in        position.value += velocity.value    }}struct ExamplePlugin: Plugin {    func setup(in app: AppWorlds) {        app.spawn {            Position(value: 0)            Velocity(value: 1)        }        app.spawn {            Position(value: 1)            Velocity(value: 2)        }        app.addSystem(MovementSystem.self, on: .update)    }}@mainstruct AdaApp: App {    var body: some AppScene {        DefaultAppWindow()            .addPlugins(ExamplePlugin())    }}\u041c\u0430\u043a\u0440\u043e\u0441 @System \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0442\u0438\u043f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0437\u0430 \u0432\u0430\u0441. \u0412\u044b \u043f\u0438\u0448\u0435\u0442\u0435 \u043b\u043e\u0433\u0438\u043a\u0443 \u043a\u0430\u043a Swift-\u0444\u0443\u043d\u043a\u0446\u0438\u044e, \u0430 AdaEngine \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0435\u0435 \u0432 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e ECS-\u0441\u0438\u0441\u0442\u0435\u043c\u0443.QueriesQueries \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0438\u0437 \u043c\u0438\u0440\u0430:@Systemfunc Movement(_ query: Query&lt;Entity, Transform&gt;) {    query.forEach { entity, transform in        \/\/ Iterate over every entity with a Transform.    }}Filter queries\u0424\u0438\u043b\u044c\u0442\u0440\u044b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u044e\u0442 \u043d\u0430\u0431\u043e\u0440 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439:@Systemfunc PlayerMovement(    _ query: FilterQuery&lt;Entity, Transform, With&lt;Player&gt;&gt;) {    query.forEach { entity, transform in        \/\/ Iterate only over entities that also have Player.    }}Change detectionChange detection \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u043e\u0433\u0434\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0440\u0435\u043b\u0435\u0432\u0430\u043d\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435:@Systemfunc EnemyHealthBar(    _ query: FilterQuery&lt;Enemy, Changed&lt;Health&gt;&gt;) {    query.forEach { enemy in        \/\/ Run when Health has been added or changed.    }}ResourcesResources \u0445\u0440\u0430\u043d\u044f\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443\u0440\u043e\u0432\u043d\u044f \u043c\u0438\u0440\u0430:struct GameScore: Resource {    var score: Int    var bulletFireCount: Int}world.insertResource(GameScore(score: 0, bulletFireCount: 0))@Systemfunc UpdateScore(score: ResMut&lt;GameScore&gt;) {    score.score += 1}Delta time \u0442\u043e\u0436\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u0430\u043a resource:@Systemfunc Movement(    time: Res&lt;DeltaTime&gt;,    query: Query&lt;Ref&lt;Position&gt;&gt;) {    query.forEach {        $0.value += 20 * time.deltaTime    }}Commands\u041a\u043e\u0433\u0434\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u043b\u0438\u0431\u043e \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Commands. \u041a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u0447\u0442\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c.@Systemfunc GameStartup(_ commands: Commands) {    commands.spawn(&#171;Player&#187;) {        Player()        Transform()    }}Local values\u0421\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u043e\u0433\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 Local:@Systemfunc UpdateData(isUpdated: Local&lt;Bool&gt; = false) {    if !isUpdated.wrappedValue {        \/\/ Perform one-time work.        isUpdated.wrappedValue = true    }}Struct systems\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f AdaECS \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 struct-based \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0447\u0435\u0440\u0435\u0437 @PlainSystem:@PlainSystem(dependencies: [    .after(EnemyMovement.self),    .before(PhysicsSystem.self)])struct MovementSystem {    @Query&lt;Player, Transform&gt;    private var playerQuery    init(world: World) {}    func update(context: UpdateContext) {        playerQuery.forEach {            \/\/ Update player movement here.        }    }}Schedulers\u0421\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432 schedulers. \u0412 AdaEngine \u0435\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432\u044b\u0435 \u0441\u0442\u0430\u0434\u0438\u0438: startup, pre-update, update, fixed update \u0438 \u0434\u0440\u0443\u0433\u0438\u0435:world    .addSystem(StartupSystem.self, on: .startup)    .addSystem(MovementSystem.self, on: .fixedUpdate)    .addSystem(UpdateEnemySystem.self, on: .preUpdate)    .addSystem(UpdateScoreSystem.self, on: .update).startup \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0435 schedulers, \u0435\u0441\u043b\u0438 \u0438\u0433\u0440\u0435 \u043d\u0443\u0436\u043d\u0430 \u0441\u0432\u043e\u044f \u043c\u043e\u0434\u0435\u043b\u044c \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.\u26a0\ufe0f \u0420\u0430\u043d\u043d\u0438\u0439 \u0440\u0435\u043b\u0438\u0437 \u0411\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0441\u0438\u0441\u0442\u0435\u043c. \u0415\u0441\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043d\u0435 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0432 \u0442\u043e\u043c \u0436\u0435 scheduler, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0443\u043f\u0430\u0441\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.BundlesBundles \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u044e\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043e\u0434\u043d\u0443 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0443\u044e \u0435\u0434\u0438\u043d\u0438\u0446\u0443. \u041c\u0430\u043a\u0440\u043e\u0441 @Bundle \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u0434, \u043d\u0443\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438 bundle \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b:@Bundlestruct EnemyBundle {    let enemy = Enemy()    let transform: Transform    let health: Health}world.spawn(    &#171;Enemy&#187;,    bundle: EnemyBundle(        transform: Transform(),        health: Health(30)    ))Scriptable objects\u0415\u0441\u043b\u0438 \u0434\u043b\u044f \u0447\u0430\u0441\u0442\u0438 gameplay-\u043a\u043e\u0434\u0430 \u0432\u0430\u043c \u0431\u043b\u0438\u0436\u0435 Unity-\u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 workflow, AdaEngine \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 ScriptableObject \u0438 ScriptableComponents:final class Player: ScriptableObject {    func update(_ deltaTime: TimeInterval) {        if input.isKeyPressed(.w) {            \/\/ Move player.        }    }}world.spawn(&#171;Player&#187;) {    ScriptableComponents(        components: [            Player()        ]    )}\u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 object-style escape hatch, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u0432\u0438\u0436\u043e\u043a \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-482545","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482545","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=482545"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/482545\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=482545"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=482545"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=482545"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}