{"id":462119,"date":"2025-06-04T21:00:33","date_gmt":"2025-06-04T21:00:33","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=462119"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=462119","title":{"rendered":"<span>RESTful API server \u043d\u0430 Unreal Engine \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 Input \u0447\u0435\u0440\u0435\u0437 HTTP<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043e \u043c\u043d\u043e\u0439 \u0432\u0441\u0442\u0430\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430: \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 Unreal Engine \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e: \u043d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Unreal Engine (\u043d\u0430\u0437\u043e\u0432\u0451\u043c \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0435\u0439), \u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u044d\u0442\u0443 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044e. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0439\u043d\u0430\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u044f\u00a0<a href=\"https:\/\/youtu.be\/vib8cg4IFUc?si=W1ujuoAHuQ8JHHmB\" rel=\"noopener noreferrer nofollow\">\u0437\u043c\u0435\u0439\u043a\u0430 \u043d\u0430 \u0444\u0430\u0441\u0430\u0434\u0435 \u0437\u0434\u0430\u043d\u0438\u044f<\/a>, \u0442\u0430\u043a \u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u043c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u043a\u0430\u043a \u0441 \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0db\/f3d\/b09\/0dbf3db0942bcc2bbeed540949f5b7e3.png\" alt=\"\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u0435\u0432\u044c\u044e\u0448\u043a\u0430\" title=\"\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u0435\u0432\u044c\u044e\u0448\u043a\u0430\" width=\"1024\" height=\"1536\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/0db\/f3d\/b09\/0dbf3db0942bcc2bbeed540949f5b7e3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/0db\/f3d\/b09\/0dbf3db0942bcc2bbeed540949f5b7e3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u0435\u0432\u044c\u044e\u0448\u043a\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u2013\u0441\u0435\u0440\u0432\u0435\u0440. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435: \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Unreal Engine, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a RPC \u0438\u043b\u0438 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0441\u0442\u0435\u043a \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b. \u041d\u043e \u0438 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043b\u0438\u0448\u043d\u0438\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u043f\u0440\u043e\u0441\u043b\u043e\u0435\u043a \u0432 \u0432\u0438\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \/ \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u043c \u0441\u0442\u0435\u043a\u0435 &#8212; \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 Unreal Engine \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 HTTP-\u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438, \u0432 \u0446\u0435\u043b\u043e\u043c, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0441 UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<h2>\u041e \u0447\u0451\u043c \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c<\/h2>\n<ol>\n<li>\n<p><a href=\"https:\/\/scheme\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/what-in-engine\" rel=\"noopener noreferrer nofollow\">\u0427\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0434\u0432\u0438\u0436\u043a\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/a>?<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/wrapper\" rel=\"noopener noreferrer nofollow\">\u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f HTTPServer<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/character-control\" rel=\"noopener noreferrer nofollow\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/client-gamepad\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442-Gamepad<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a href=\"https:\/\/the-end\" rel=\"noopener noreferrer nofollow\">\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u043f\u0438\u043b\u043e\u0433\u0430<\/a><\/p>\n<p><a class=\"anchor\" name=\"scheme\" id=\"scheme\"><\/a><\/p>\n<h3>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/h3>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<ul>\n<li>\n<p>\u043d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043f\u0440\u043e\u0435\u043a\u0442 Unreal Engine, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u0430\u044f \u0441\u0446\u0435\u043d\u0430 \u0441 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c. HTTP-\u0441\u0435\u0440\u0432\u0435\u0440, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432 \u0441\u0446\u0435\u043d\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435-\u0433\u0435\u0439\u043c\u043f\u0430\u0434, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 HTTP \u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0447\u0435\u0440\u0435\u0437 Wi-Fi, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043a \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443 \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 UE-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. Unreal Engine \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u0432 \u0441\u0446\u0435\u043d\u0435.<\/p>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0438\u0433\u0440\u043e\u0432\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 HTTP-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 RPC-\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0438\u043b\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b49\/b8b\/007\/b49b8b007b79b4f72a7cc993e1ccb79b.png\" alt=\"\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u043a\u0430\" title=\"\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u043a\u0430\" width=\"1536\" height=\"1024\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/b49\/b8b\/007\/b49b8b007b79b4f72a7cc993e1ccb79b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b49\/b8b\/007\/b49b8b007b79b4f72a7cc993e1ccb79b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u043a\u0430<\/figcaption><\/div>\n<\/figure>\n<p><a class=\"anchor\" name=\"what-in-engine\" id=\"what-in-engine\"><\/a><\/p>\n<h3>\u0427\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0434\u0432\u0438\u0436\u043a\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>Unreal Engine \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043c\u043d\u043e\u0433\u0438\u0435 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb. \u041a\u043e\u0433\u0434\u0430 \u0440\u0435\u0447\u044c \u0437\u0430\u0445\u043e\u0434\u0438\u0442 \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445:<\/p>\n<ol>\n<li>\n<p>\u041c\u043e\u0434\u0443\u043b\u044c\u00a0<code>Sockets<\/code>\u00a0\u042d\u0442\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 API \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438, \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 \u2014 \u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 TCP-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0442\u0440\u0430\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u043d \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0442\u0435\u043c, \u043a\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c, \u043d\u043e \u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u044b\u0445 MVP \u0438\u043b\u0438 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0443\u043b\u044c\u00a0<code>Runtime\/Online\/HTTPServer<\/code>\u00a0\u041f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 Unreal Engine \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 4.25 (c \u043c\u0430\u044f 2019). \u042d\u0442\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c REST-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 UE \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0432\u0440\u043e\u0434\u0435 Node.js, Python \u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0441\u043a\u0443\u0434\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u043e\u043d \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0445 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 API, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u041f\u041e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d\u00a0<code>RemoteControl<\/code>\u00a0\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 2019 \u0433\u043e\u0434\u0443 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 HTTPServer. \u041f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432 \u0441\u0446\u0435\u043d\u0435 \u0447\u0435\u0440\u0435\u0437 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b.\u00a0<code>RemoteControlAPI<\/code>\u00a0\u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0430\u043a\u0442\u043e\u0440\u0430\u043c, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0438 \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0446\u0435\u043d\u044b, \u0438\u043c\u0435\u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0447\u0442\u043e \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0435\u043c\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438, \u044f \u043f\u0440\u0438\u0448\u0451\u043b \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043d\u0430\u0438\u043b\u0443\u0447\u0448\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u043c\u043e\u0434\u0443\u043b\u044c\u00a0<code>HTTPServer<\/code>. <s>\u041e\u043d \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u0443 \u0432 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0438<\/s>. \u041e\u043d \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0438\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043e\u0431\u0451\u0440\u0442\u043a\u0443, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043e\u0442\u0432\u0435\u0442\u043e\u0432, \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u044f \u043e\u0442 \u0440\u0443\u0442\u0438\u043d\u044b \u0438 \u0443\u0441\u043a\u043e\u0440\u044f\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u042d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0433\u0438\u0431\u043a\u0438\u043c, \u043b\u0451\u0433\u043a\u0438\u043c \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u043e\u0439 \u0434\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"wrapper\" id=\"wrapper\"><\/a><\/p>\n<h2> \u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f HTTPServer  <\/h2>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 RESTful API \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0435\u0441\u043b\u0438 \u043d\u0430\u0431\u043e\u0440 endpoints \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0444\u0438\u0433, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0443\u0431\u0438\u0440\u0430\u044f \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 UE \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e\u00a0<code>HTTPServer<\/code>\u00a0\u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u0435\u0451 \u0432 \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0430 GitHub:  <\/p>\n<p><a href=\"https:\/\/github.com\/lpestl\/HttpServerPlugin\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerPlugin<\/a><\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c, \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 MVP. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u2014 \u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u043a\u0430\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435, \u0442\u0430\u043a \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b. \u0415\u0441\u043b\u0438 \u0432\u0430\u0441 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u044d\u0442\u043e\u0442 \u0440\u0430\u0437\u0434\u0435\u043b \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c. <\/p>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u0441\u0442\u0430\u0434\u0438\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0451\u043c\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u0441\u0451 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 Blueprint.<\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443\u00a0<code>FEndpointData<\/code>\u00a0\u0438 \u043a\u043b\u0430\u0441\u0441\u00a0<code>UHttpServerSettings<\/code>, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432:<\/p>\n<pre><code class=\"cpp\">USTRUCT(BlueprintType) struct HTTPSERVERWRAPPERMODULE_API FEndpointData { GENERATED_BODY()  UPROPERTY(EditAnywhere, BlueprintReadWrite) FString Endpoint {};  UPROPERTY(EditAnywhere, BlueprintReadWrite) EHttpServerWrapperRequestVerbs Verbs {}; };     UCLASS(DisplayName=\"HTTP Server Settings\", Config = \"HttpServer\", DefaultConfig) class HTTPSERVERWRAPPERMODULE_API UHttpServerSettings : public UDeveloperSettings { GENERATED_BODY()  public:     \/*     Something else     *\/  private: UPROPERTY(meta = (AllowPrivateAccess = \"true\"), Config, EditAnywhere, BlueprintReadOnly, Category = \"General\") int32 Port { 8080 };  UPROPERTY(meta = (AllowPrivateAccess = \"true\"), Config, EditAnywhere, BlueprintReadOnly, Category = \"General\") TArray&lt;FEndpointData&gt; Endpoints {}; };<\/code><\/pre>\n<p>\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435\u00a0<code>UHttpServerSettings<\/code>\u00a0\u043a\u0430\u043a \u043f\u043e\u0442\u043e\u043c\u043a\u0430\u00a0<code>UDeveloperSettings<\/code>\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435:\u00a0<code>UnrealEditor \u2192 Project Settings<\/code>:  <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/53b\/47c\/106\/53b47c10683166ee967e0351d2bddcd3.png\" width=\"1105\" height=\"710\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/53b\/47c\/106\/53b47c10683166ee967e0351d2bddcd3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/53b\/47c\/106\/53b47c10683166ee967e0351d2bddcd3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u043e\u043d \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u043a\u0430\u043a BlueprintType, Blueprintable, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0435\u0439 \u0432 \u0431\u043b\u044e\u043f\u0440\u0438\u043d\u0442\u0430\u0445.  <\/p>\n<pre><code class=\"cpp\">UCLASS(BlueprintType, Blueprintable) class HTTPSERVERWRAPPERMODULE_API UHttpServer : public UObject<\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:  <\/p>\n<pre><code class=\"cpp\">UFUNCTION(BlueprintCallable, Category = \"HttpServer\") void StartApiServer();  UFUNCTION(BlueprintCallable, Category = \"HttpServer\") void StopApiServer();<\/code><\/pre>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u0432\u0441\u0435\u0445 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 endpoint&#8217;\u043e\u0432 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443, \u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u2014 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432. \u0412\u0441\u0451 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437:  <\/p>\n<pre><code class=\"cpp\">\/\/~~~ HEADER ~~~  \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u043b\u0430\u0441\u0441 \u0432 HEADER private: \/** Http router handle *\/ TSharedPtr&lt;IHttpRouter&gt; HttpRouter;  \/** Mapping of routes to delegate handles *\/ TMap&lt;FString, FHttpRouteHandle&gt; ActiveRouteHandles;  \/\/~~~ CPP ~~~  \/\/ \u0418 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \"\u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439\" (\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430) void UHttpServer::StartApiServer() { FHttpServerModule&amp; HttpServerModule = FHttpServerModule::Get();      \/\/ \u0411\u0435\u0440\u0451\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\/\u043a\u043e\u043d\u0444\u0438\u0433 UHttpServerSettings* Settings = UHttpServerSettings::Get(); if (IsValid(Settings)) { if (HttpRouter) { HttpRouter.Reset(); } HttpRouter = FHttpServerModule::Get().GetHttpRouter(Settings-&gt;GetPort(), \/* bFailOnBindFailure = *\/ true); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"Starting HttpServer on %d port:\"), Settings-&gt;GetPort());  TArray&lt;FEndpointData&gt; Endpoints = Settings-&gt;GetEndpoints(); for (FEndpointData&amp; EndpointData : Endpoints) { FHttpPath EndpointPath = EndpointData.Endpoint; EHttpServerRequestVerbs Verbs = static_cast&lt;EHttpServerRequestVerbs&gt;(EndpointData.Verbs);  ActiveRouteHandles.Add( EndpointData.Endpoint,                 \/* \u0422\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0447\u0438\u043a HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431 Endpoint *\/ HttpRouter-&gt;BindRoute( EndpointPath, Verbs, FHttpRequestHandler::CreateUObject(this, &amp;UHttpServer::HandleRequest, EndpointData) ) ); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"\\t%s: %s \"), *StaticEnum&lt;EHttpServerWrapperRequestVerbs&gt;()-&gt;GetNameStringByValue(static_cast&lt;int64&gt;(EndpointData.Verbs)), *EndpointData.Endpoint); }          \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 HttpServerModule.StartAllListeners(); } }  \/\/ \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 void UHttpServer::StopApiServer() {     \/\/ \u0415\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u0432\u0438\u0436\u043a\u043e\u0432\u044b\u0439 HTTP Server \u043c\u043e\u0434\u0443\u043b\u044c if (FHttpServerModule::IsAvailable()) {         FHttpServerModule&amp; HttpServerModule = FHttpServerModule::Get();         \/\/ \u0421\u0442\u043e\u043f\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 HttpServerModule.StopAllListeners();  UHttpServerSettings* Settings = UHttpServerSettings::Get(); if (IsValid(Settings)) { TArray&lt;FEndpointData&gt; Endpoints = Settings-&gt;GetEndpoints(); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"Unbound endpoints:\")); \/\/ \u041f\u0440\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u0432\u0441\u0435\u043c \"\u043d\u0430\u043a\u043e\u043d\u0444\u0438\u0436\u0435\u043d\u043d\u044b\u043c\" \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c for (FEndpointData&amp; EndpointData : Endpoints) { if (ActiveRouteHandles.Find(EndpointData.Endpoint) != nullptr) { if (ActiveRouteHandles[EndpointData.Endpoint].IsValid()) { UE_LOG(LogHttpServerPlugin, Log, TEXT(\"\\t* %s\"), *EndpointData.Endpoint);                         \/\/ \u0418 \u043e\u0442\u043f\u0438\u0448\u0435\u043c\u0441\u044f \u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 HttpServerModule.GetHttpRouter(Settings-&gt;GetPort())-&gt;UnbindRoute(ActiveRouteHandles[EndpointData.Endpoint]); } } } } ActiveRouteHandles.Reset(); }  if (HttpRouter) { HttpRouter.Reset(); } }<\/code><\/pre>\n<p>\u0414\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u044f \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0434\u0435\u043b\u0435\u0433\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u042d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e, \u0435\u0441\u043b\u0438 \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432 Blueprint, \u043d\u0435 \u043b\u0435\u0437\u044f \u0432 C++:  <\/p>\n<pre><code class=\"cpp\">DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FOnReceivedRequest, const FString&amp;, RequestBody, FEndpointData, EndpointData);  public: FOnReceivedRequest&amp; OnReceivedRequest() { return Delegate_OnReceivedRequest; } private: UPROPERTY(BlueprintAssignable) FOnReceivedRequest Delegate_OnReceivedRequest;<\/code><\/pre>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043a\u043e\u0434\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 HandleRequest, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0442\u0432\u0435\u0442\u0430:  <\/p>\n<pre><code class=\"cpp\">\/\/ In HEADER virtual bool HandleRequest(const FHttpServerRequest&amp; Request, const FHttpResultCallback&amp; OnComplete, FEndpointData EndpointData);  \/\/ In CPP bool UHttpServer::HandleRequest(const FHttpServerRequest&amp; Request, const FHttpResultCallback&amp; OnComplete, FEndpointData EndpointData) { FString RequestBody = FString(Request.Body.Num(), UTF8_TO_TCHAR(Request.Body.GetData())); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"Received request: \\n%s\"), *RequestBody);  \/\/ Parse JSON from body request TSharedPtr&lt;FJsonObject&gt; JsonRequest; TSharedRef&lt;TJsonReader&lt;&gt;&gt; Reader = TJsonReaderFactory&lt;&gt;::Create(RequestBody);  if (!FJsonSerializer::Deserialize(Reader, JsonRequest) || !JsonRequest.IsValid()) { return ProcessResponse(OnComplete, TEXT(\"Error\"), TEXT(\"Invalid JSON format\"), EHttpServerResponseCodes::BadRequest); }  if (Delegate_OnReceivedRequest.IsBound()) { Delegate_OnReceivedRequest.Broadcast(RequestBody, EndpointData); }  return ProcessResponse(OnComplete, TEXT(\"Status\"), TEXT(\"Request Handled. Everything is OK\"), EHttpServerResponseCodes::Accepted); }<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 <code>ProcessResponse<\/code> \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 JSON-\u043e\u0442\u0432\u0435\u0442\u0430, \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432.<\/p>\n<p>\u0412\u041d\u0418\u041c\u0410\u041d\u0418\u0415 \u26a0\ufe0f: \u0412 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u00a0<code>HandleRequest<\/code>\u00a0\u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0432\u043e\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f\u00a0<code>HttpResponse<\/code>, \u043d\u043e \u0443\u0436\u0435 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<pre><code class=\"cpp\">bool UHttpServer::ProcessResponse(const FHttpResultCallback&amp; OnComplete, const FString&amp; Key, const FString&amp; MessageText, EHttpServerResponseCodes ResponseCode) { const bool bIsError = static_cast&lt;uint16&gt;(ResponseCode) &gt;= 400; if (bIsError) { UE_LOG(LogHttpServerPlugin, Error, TEXT(\"%s: %s\"), *Key, *MessageText); } else { UE_LOG(LogHttpServerPlugin, Log, TEXT(\"%s: %s\"), *Key, *MessageText); } \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c JSON \u0434\u043b\u044f \u0442\u0435\u043b\u0430 \u043e\u0442\u0432\u0435\u0442\u0430 TSharedPtr&lt;FJsonObject&gt; MessageResponse = MakeShareable(new FJsonObject()); \/\/ \u0414\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435     MessageResponse-&gt;SetStringField(Key, MessageText);     \/\/ \u041a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 FString MessageResponseString; TSharedRef&lt;TJsonWriter&lt;&gt;&gt; Writer = TJsonWriterFactory&lt;&gt;::Create(&amp;MessageResponseString); FJsonSerializer::Serialize(MessageResponse.ToSharedRef(), Writer);      \/\/ \u0421\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0442\u0432\u0435\u0442 TUniquePtr&lt;FHttpServerResponse&gt; Response = FHttpServerResponse::Create(MessageResponseString, TEXT(\"application\/json\")); Response-&gt;Code = ResponseCode;     \/\/ \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u043c Callback OnComplete(MoveTemp(Response));  return !bIsError; }<\/code><\/pre>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f\u00a0<code>UHttpServer<\/code>, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c, \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0435\u0439, \u0435\u0451 \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437\u00a0<code>UGameInstanceSubsystem<\/code>,\u00a0<code>UWorldSubsystem<\/code>\u00a0\u0438\u043b\u0438\u00a0<code>AGameMode<\/code>.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0432 GameMode:<\/p>\n<pre><code class=\"cpp\">#include \"SomeNewGameMode.h\" #include \"HttpServer.h\"  void ASomeNewGameMode::BeginPlay() {     Super::BeginPlay();     HttpServer = NewObject&lt;UHttpServer&gt;();     HttpServer-&gt;OnReceivedRequest().AddDynamic(this, &amp;ASomeNewGameMode::OnReceivedRequest);     HttpServer-&gt;StartApiServer(); }  void ASomeNewGameMode::OnReceivedRequest(const FString&amp; RequestBody, FEndpointData EndpointData) {     \/\/... }  void ASomeNewGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason) {     HttpServer-&gt;StopApiServer();     Super::EndPlay(EndPlayReason); }<\/code><\/pre>\n<p><a class=\"anchor\" name=\"character-control\" id=\"character-control\"><\/a><\/p>\n<h3>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c<\/h3>\n<p>\u0414\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u044f \u0431\u0443\u0434\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439\u00a0<code>SideScrollerTemplate<\/code>\u00a0\u0430\u0434\u0430\u043f\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043f\u043e\u0434 UE 5.5.  <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/eb7\/576\/eae\/eb7576eae3376e891b529c88024a1522.png\" alt=\"SideScrollerTemplate for UE5\" title=\"SideScrollerTemplate for UE5\" width=\"3368\" height=\"807\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/eb7\/576\/eae\/eb7576eae3376e891b529c88024a1522.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/eb7\/576\/eae\/eb7576eae3376e891b529c88024a1522.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>SideScrollerTemplate for UE5<\/figcaption><\/div>\n<\/figure>\n<ul>\n<li>\n<p>\u041f\u043e\u0434\u043b\u044e\u0447\u0438\u043c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u043b\u0430\u0433\u0438\u043d:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpServerPlugin\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerPlugin<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043d\u0430 \u043c\u043e\u0434\u0443\u043b\u044c, \u0438\u0437\u043c\u0435\u043d\u0438\u0432 \u0432 \u0444\u0430\u0439\u043b\u0435\u00a0<code>*.Build.cs<\/code>\u00a0\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"cs\">PublicDependencyModuleNames.AddRange(new string[] { \"Core\", \"CoreUObject\", \"Engine\", \"InputCore\", \"HttpServerWrapperModule\" });<\/code><\/pre>\n<ul>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0444\u0438\u0433\u0435\u00a0<code>{project_path}\/Config\/DefaultHttpServer.ini<\/code>\u00a0\u0437\u0430\u0434\u0430\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u0447\u0435\u043d\u044c endpoint\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u0443\u0434\u0443\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0442\u044c \u0437\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"css\">[\/Script\/HttpServerWrapperModule.HttpServerSettings] Port=8080 +Endpoints=(Endpoint=\"\/version\",Verbs=VERB_GET) +Endpoints=(Endpoint=\"\/up\/pressed\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/up\/released\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/left\/pressed\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/left\/released\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/right\/pressed\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/right\/released\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/a-button\/pressed\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/a-button\/released\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/b-button\/pressed\",Verbs=VERB_POST) +Endpoints=(Endpoint=\"\/b-button\/released\",Verbs=VERB_POST)<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u0441\u0432\u043e\u0439\u00a0<code>APlayerController<\/code>, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432\u00a0<code>GameMode<\/code>\u00a0\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432 \u043d\u0451\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f. \u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">UCLASS() class HTTPSERVERDEMO_API AHttpPlayerController : public APlayerController { GENERATED_BODY()  public: AHttpPlayerController();  virtual void BeginPlay() override; virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;  UFUNCTION() void OnRecevedHttpInput(const FString&amp; RequestBody, FEndpointData EndpointData);  private: UPROPERTY(EditAnywhere) UHttpServer* HttpInputReceiver { nullptr }; };<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434\u044b\u00a0<code>BeginPlay<\/code>\u00a0\u0438\u00a0<code>EndPlay<\/code>\u00a0\u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u043c \u0432\u044b\u0448\u0435, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u0435\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 HTTP-\u0438\u043d\u043f\u0443\u0442\u0430:  <\/p>\n<pre><code class=\"cpp\">void AHttpPlayerController::OnRecevedHttpInput(const FString&amp; RequestBody, FEndpointData EndpointData) { if (IsValid(GetCharacter())) { if (EndpointData.Endpoint.Contains(TEXT(\"\/up\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/up\/released\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/left\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/left\/released\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/right\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/right\/released\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/a-button\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/a-button\/released\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/b-button\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/b-button\/released\"))){} } }<\/code><\/pre>\n<p>\u041f\u0440\u044b\u0436\u043e\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u043c\u0435\u0442\u043e\u0434\u0430\u043c\u0438\u00a0<code>ACharacter<\/code>. \u0414\u043b\u044f \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u044f \u0432\u043b\u0435\u0432\u043e \u0438 \u0432\u043f\u0440\u0430\u0432\u043e \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 workaround: \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u0444\u043b\u0430\u0433\u0438 \u0438 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435. \u041e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c Tick:  <\/p>\n<pre><code class=\"cpp\">\/\/ ~~~ HEADER ~~~ public:     \/* ... *\/ virtual void Tick(float DeltaSeconds) override; private:     \/* ... *\/ bool bMovePressed { false }; float MoveScale { 0.f };   \/\/ ~~~ CPP ~~~ void AHttpPlayerController::OnRecevedHttpInput(const FString&amp; RequestBody, FEndpointData EndpointData) { if (IsValid(GetCharacter())) {         \/\/ \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u043f\u0440\u044b\u0436\u043a\u0430 \u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u0438\u043b\u0438 \u0435\u0451 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0443 if (EndpointData.Endpoint.Contains(TEXT(\"\/up\/pressed\"))) { GetCharacter()-&gt;Jump(); } else if (EndpointData.Endpoint.Contains(TEXT(\"\/up\/released\"))) { GetCharacter()-&gt;StopJumping(); }         \/\/ \u041f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \"\u0432\u043b\u0435\u0432\u043e\" \u0438\u043b\u0438 \"\u0432\u043f\u0440\u0430\u0432\u043e\" \u0438 \u0437\u0430\u043f\u043e\u043c\u043d\u0438\u043b\u0438 \u043d\u0430\u0436\u0430\u0442\u0430 \u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 else if (EndpointData.Endpoint.Contains(TEXT(\"\/left\/pressed\"))) { bMovePressed = true; \/\/ \u043a\u043d\u043e\u043f\u043a\u0430 \"\u0432\u043b\u0435\u0432\u043e\" MoveScale = 1.f; \/\/ MoveScale - \u043e\u043f\u0435\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u044f.             \/\/ \u0415\u0441\u043b\u0438 MoveScale &gt; 0 - \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043b\u0435\u0432\u043e (\u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0441\u0438 Y \u043d\u0430 \u0441\u0446\u0435\u043d\u0435) } else if (EndpointData.Endpoint.Contains(TEXT(\"\/left\/released\"))) { bMovePressed = false; \/\/ \u043a\u043d\u043e\u043f\u043a\u0443 \u043e\u0442\u043f\u0443\u0441\u0442\u0438\u043b\u0438 MoveScale = 0.f; \/\/ \u0415\u0441\u043b\u0438 MoveScale == 0, \u0442\u043e \u0438 \u0441\u043c\u0435\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 } else if (EndpointData.Endpoint.Contains(TEXT(\"\/right\/pressed\"))) { bMovePressed = true; \/\/ \u043a\u043d\u043e\u043f\u043a\u0430 \"\u0432\u043f\u0440\u0430\u0432\u043e\" \u043d\u0430\u0436\u0430\u0442\u0430 MoveScale = -1.f;             \/\/ \u0415\u0441\u043b\u0438 MoveScale &lt; 0 - \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0432\u043f\u0440\u0430\u0432\u043e (\u043e\u0442\u0440\u0438\u0446\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0441\u0438 Y \u043d\u0430 \u0441\u0446\u0435\u043d\u0435) } else if (EndpointData.Endpoint.Contains(TEXT(\"\/right\/released\"))) { bMovePressed = false; \/\/ \u043a\u043d\u043e\u043f\u043a\u0443 \u043e\u0442\u043f\u0443\u0441\u0442\u0438\u043b\u0438 MoveScale = 0.f; \/\/ \u0415\u0441\u043b\u0438 MoveScale == 0, \u0442\u043e \u0438 \u0441\u043c\u0435\u0436\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 } else if (EndpointData.Endpoint.Contains(TEXT(\"\/a-button\/pressed\"))) { GetCharacter()-&gt;Jump(); } else if (EndpointData.Endpoint.Contains(TEXT(\"\/a-button\/released\"))) { GetCharacter()-&gt;StopJumping(); } else if (EndpointData.Endpoint.Contains(TEXT(\"\/b-button\/pressed\"))){} else if (EndpointData.Endpoint.Contains(TEXT(\"\/b-button\/released\"))){} } }  void AHttpPlayerController::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds);      \/\/ \u0412 \u0442\u0438\u043a\u0435 \u043f\u0435\u0440\u0435\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c MovementInput \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0443, \u043f\u043e\u043a\u0430 \u043a\u043d\u043e\u043f\u043a\u0430 \"\u0432\u043f\u0440\u0430\u0432\u043e\" \u0438\u043b\u0438 \"\u0432\u043b\u0435\u0432\u043e\" \u043d\u0430\u0436\u0430\u0442\u0430 if (bMovePressed &amp;&amp; IsValid(GetCharacter())) {         GetCharacter()-&gt;AddMovementInput(FVector(0.0f, 1.0f, 0.0f), MoveScale); } }<\/code><\/pre>\n<p>\u041f\u043e\u0447\u0442\u0438 \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e. \u0422\u0435\u043f\u0435\u0440\u044c, \u0432\u043e\u043e\u0440\u0443\u0436\u0438\u0432\u0448\u0438\u0441\u044c\u00a0<a href=\"https:\/\/www.postman.com\/\" rel=\"noopener noreferrer nofollow\">Postman<\/a>, Curl \u0438\u043b\u0438 \u0447\u0442\u043e-\u0431\u044b-\u0442\u0430\u043c-\u043d\u0438-\u0431\u044b\u043b\u043e, \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u0451\u043c HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d93\/aa6\/aa3\/d93aa6aa34ccb7fd712646a121de4dca.png\" alt=\"\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0437 Postman\" title=\"\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0437 Postman\" width=\"1789\" height=\"587\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/d93\/aa6\/aa3\/d93aa6aa34ccb7fd712646a121de4dca.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d93\/aa6\/aa3\/d93aa6aa34ccb7fd712646a121de4dca.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0437 Postman<\/figcaption><\/div>\n<\/figure>\n<p>\u26a0\ufe0f \u0412\u0430\u0436\u043d\u044b\u0435 \u0437\u0430\u043c\u0435\u0447\u0430\u043d\u0438\u044f:<\/p>\n<ul>\n<li>\n<p>\u0412 Unreal Engine 5 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f 5.5) \u043c\u043e\u0434\u0443\u043b\u044c HTTPServer \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 HTTPS \u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438 \u2014 \u043e\u043d \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0445 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043b\u0443\u0448\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e 127.0.0.1, \u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0441 \u0434\u0440\u0443\u0433\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f. \u0427\u0442\u043e\u0431\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0432 Config\/DefaultEngine.ini \u0434\u043e\u0431\u0430\u0432\u044c\u0442\u0435:<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"css\">[HTTPServer.Listeners] DefaultBindAddress=0.0.0.0<\/code><\/pre>\n<p>\u0414\u0435\u043c\u043e-\u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpServerDemo\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerDemo<\/a>  <\/p>\n<p><a class=\"anchor\" name=\"client-gamepad\" id=\"client-gamepad\"><\/a><\/p>\n<h3>\u041f\u0438\u0448\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442-Gamepad<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043f\u0430\u0443\u0437\u0443 \u043e\u0442 Unreal Engine \u0438 C++. \u041f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043e\u0442\u043b\u0438\u0447\u043d\u044b\u0439 \u043f\u043e\u0432\u043e\u0434 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c .NET MAUI \u2014 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0439 UI-\u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a. \u0418\u043c\u0435\u043d\u043d\u043e \u043d\u0430 \u043d\u0451\u043c \u0438 \u0431\u0443\u0434\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043a\u043b\u0438\u0435\u043d\u0442-\u0433\u0435\u0439\u043c\u043f\u0430\u0434 \u0434\u043b\u044f \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.  <\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4a1\/7cf\/efa\/4a17cfefa1e69f56fc17d404570ee677.png\" alt=\"\u041d\u0443 \u043d\u0430\u0434\u043e \u0436\u0435! \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u0438 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e!\" title=\"\u041d\u0443 \u043d\u0430\u0434\u043e \u0436\u0435! \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u0438 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e!\" width=\"4096\" height=\"3072\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/4a1\/7cf\/efa\/4a17cfefa1e69f56fc17d404570ee677.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4a1\/7cf\/efa\/4a17cfefa1e69f56fc17d404570ee677.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041d\u0443 \u043d\u0430\u0434\u043e \u0436\u0435! \u041a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0447\u043d\u043e \u0438 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e!<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043e\u0441\u043d\u043e\u0432\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0451\u043c \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0433\u0435\u0439\u043c\u043f\u0430\u0434 \u043e\u0442 NES \u0438 \u0441\u0432\u0435\u0440\u0441\u0442\u0430\u0435\u043c \u0435\u0433\u043e \u0430\u043d\u0430\u043b\u043e\u0433 \u0432 XAML. \u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0430\u0437\u043c\u0435\u0442\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043e\u0431\u044a\u0451\u043c\u043d\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0438\u0436\u0435 \u043f\u0440\u0438\u0432\u0435\u0434\u0451\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u0438 \u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0433\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430:<\/p>\n<pre><code class=\"xml\">&lt;?xaml version=\"1.0\" encoding=\"utf-8\" ?&gt; &lt;ContentPage xmlns=\"http:\/\/schemas.microsoft.com\/dotnet\/2021\/maui\"              xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\"              xmlns:viewModels=\"clr-namespace:HttpGamepadInput.ViewModels\"              xmlns:base=\"clr-namespace:HttpGamepadInput.BaseClasses\"              x:Class=\"HttpGamepadInput.Views.MainPage\"              Background=\"White\"              x:DataType=\"viewModels:GamepadViewModel\"&gt;          &lt;ContentPage.BindingContext&gt;         &lt;viewModels:GamepadViewModel \/&gt;     &lt;\/ContentPage.BindingContext&gt;          &lt;Grid BackgroundColor=\"#282838\" ColumnDefinitions=\"*,*,*\" Margin=\"10,25,10,10\"&gt;                  &lt;!-- D-Pad Column --&gt;         &lt;Grid ... &gt; ... &lt;\/Grid&gt;                  &lt;!-- Select\/Start Column --&gt;         &lt;Grid ... &gt; ... &lt;\/Grid&gt;                  &lt;!-- A \/ B Buttons Column --&gt;         &lt;Grid Grid.Column=\"2\" RowDefinitions=\"*,Auto,*\"&gt;             &lt;Grid Grid.Row=\"1\" RowDefinitions=\"0.4*,*,0.2*,*,0.4*\" ColumnDefinitions=\"0.3*,*,0.2*,*,0.3*\"&gt;                  &lt;!-- B Turbo Holder --&gt;                 &lt;Grid Grid.Row=\"3\" Grid.Column=\"1\"                       HorizontalOptions=\"Fill\"                       VerticalOptions=\"Fill\"                       HeightRequest=\"{Binding Source={x:Reference BHolderBox}, Path=Width}\"&gt;                 &lt;\/Grid&gt;                  &lt;!-- A Turbo Holder --&gt;                 &lt;Grid Grid.Row=\"1\" Grid.Column=\"3\"                       HorizontalOptions=\"Fill\"                       VerticalOptions=\"Fill\"                       HeightRequest=\"{Binding Source={x:Reference AHolderBox}, Path=Width}\"&gt;                 &lt;\/Grid&gt;                                  &lt;!-- B Button Holder --&gt;                 &lt;Grid ... &gt; ... &lt;\/Grid&gt;                                  &lt;!-- A Button Holder --&gt;                 &lt;Grid ... &gt; ... &lt;\/Grid&gt;                                  &lt;Label Grid.Row=\"4\" Grid.Column=\"1\"                        x:Name=\"BLabel\"                        Text=\"B\"                         TextColor=\"Red\"                         FontSize=\"12\"                         FontAttributes=\"Bold\"                        HorizontalTextAlignment=\"End\"\/&gt;                 &lt;Label Grid.Row=\"4\" Grid.Column=\"3\"                        x:Name=\"ALabel\"                        Text=\"A\"                         TextColor=\"Red\"                         FontSize=\"12\"                         FontAttributes=\"Bold\"                        HorizontalTextAlignment=\"End\"\/&gt;             &lt;\/Grid&gt;         &lt;\/Grid&gt;     &lt;\/Grid&gt; &lt;\/ContentPage&gt;<\/code><\/pre>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f82\/1c4\/a0b\/f821c4a0b287e696b729a17856f72dd3.png\" alt=\"\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0433\u0438\u0438...\" title=\"\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0433\u0438\u0438...\" width=\"600\" height=\"450\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/f82\/1c4\/a0b\/f821c4a0b287e696b729a17856f72dd3.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/f82\/1c4\/a0b\/f821c4a0b287e696b729a17856f72dd3.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0433\u0438\u0438&#8230;<\/figcaption><\/div>\n<\/figure>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/021\/292\/291\/0212922916b522700fd0afb93c068d0c.png\" alt=\"...\u0438 \u0433\u043e\u0442\u043e\u0432\u043e!\" title=\"...\u0438 \u0433\u043e\u0442\u043e\u0432\u043e!\" width=\"2564\" height=\"942\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/021\/292\/291\/0212922916b522700fd0afb93c068d0c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/021\/292\/291\/0212922916b522700fd0afb93c068d0c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>&#8230;\u0438 \u0433\u043e\u0442\u043e\u0432\u043e!<\/figcaption><\/div>\n<\/figure>\n<p>\u0414\u043b\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u043f\u0430\u0442\u0442\u0435\u0440\u043d MVVM (Model\u2013View\u2013ViewModel). \u0412 ViewModel \u043e\u043f\u0438\u0441\u0430\u043d\u044b \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043a\u043d\u043e\u043f\u043e\u043a \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043b\u0435\u0435 \u0431\u0438\u043d\u0434\u044f\u0442\u0441\u044f \u0432 XAML:  <\/p>\n<pre><code class=\"cs\">using System.Windows.Input; using System.Diagnostics; using System.Net.Http.Headers; using System.Text; using HttpGamepadInput.BaseClasses;  namespace HttpGamepadInput.ViewModels;  public class GamepadViewModel : BindableBase {     #region ~ Commands Properties ~     \/\/ D-Pad commands     public ICommand UpButtonPressedCommand { get; }     public ICommand UpButtonReleasedCommand { get; }      \/* Other commands properties *\/      #endregion      private HttpClient _client = new HttpClient();          #region ~ Constructor ~     public GamepadViewModel()     {         UpButtonPressedCommand = new Command(OnUpButtonPressed);         UpButtonReleasedCommand = new Command(OnUpButtonReleased);  \/* Other commands *\/     }     #endregion          #region ~ Commands implementstions ~          private async void OnUpButtonPressed()     {         Debug.WriteLine(\"[INFO] UP pressed\");         await PostButtonStatus(\"up\/pressed\");     } \/* Other buttons *\/     #endregion }<\/code><\/pre>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438\u00a0<code>GamepadViewModel<\/code>\u00a0\u0441\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u00a0<code>HttpClient<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0438 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0443 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 Unreal Engine:  <\/p>\n<pre><code class=\"cs\">private HttpClient _client = new HttpClient();          private string _serverUrl = \"http:\/\/127.0.0.1:8080\/\";     public string ServerUrl     {         get =&gt; _serverUrl;         set         { \/\/ \u0415\u0441\u043b\u0438 \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c ServerUrl             if (SetProperty(ref _serverUrl, value))             { \/\/ \u0442\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c HTTP Client                 UpdateHttpClient();             }         }     }      \/* ~ Constructor ~ *\/  \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 HTTP Client \u0441 \u0431\u0430\u0437\u043e\u0432\u044b\u043c \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c     private void UpdateHttpClient()     {         _client = new HttpClient         {             BaseAddress = new Uri(ServerUrl)         };         _client.DefaultRequestHeaders.Accept.Clear();         _client.DefaultRequestHeaders.Accept.Add(             new MediaTypeWithQualityHeaderValue(\"application\/json\"));     }      \/\/ \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043f\u0443\u0441\u0442\u043e\u0439 POST \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 endpoint, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430     public async Task PostButtonStatus(string relativeUrl)     {         var content = new StringContent(\"{}\", Encoding.UTF8, \"application\/json\");          HttpResponseMessage response = await _client.PostAsync(relativeUrl, content);         if (response.IsSuccessStatusCode)         {             string responseBody = await response.Content.ReadAsStringAsync();             Debug.WriteLine($\"Response from {relativeUrl}: {responseBody}\");         }         else         {             Debug.WriteLine($\"Error posting to {relativeUrl}: {response.StatusCode}\");         }     }          \/* ~ Commands implementstions ~ *\/<\/code><\/pre>\n<p>\u041c\u0435\u0442\u043e\u0434 PostButtonStatus \u2014 \u044d\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0430\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 POST-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u043f\u0443\u0441\u0442\u044b\u043c \u0442\u0435\u043b\u043e\u043c (\u0432 \u0432\u0438\u0434\u0435 {}), \u0433\u0434\u0435 relativeUrl \u2014 \u044d\u0442\u043e endpoint, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0436\u0430\u0442\u0438\u044e \u0438\u043b\u0438 \u043e\u0442\u043f\u0443\u0441\u043a\u0430\u043d\u0438\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u0432 \u043b\u043e\u0433 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0442\u0435\u043b\u043e \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0438\u043d\u0430\u0447\u0435 \u2014 \u043a\u043e\u0434 \u043e\u0448\u0438\u0431\u043a\u0438.<\/p>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0437\u0434\u0435\u0441\u044c:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpGamepadInput\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpGamepadInput<\/a><\/p>\n<p>\u041d\u0438\u0436\u0435 \u2014 \u043f\u0440\u0438\u043c\u0435\u0440 \u0440\u0430\u0431\u043e\u0442\u044b \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0441\u0432\u044f\u0437\u043a\u0435:\u00a0<code>\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442<\/code>\u00a0&lt;-&gt;\u00a0<code>UE server<\/code>\u00a0\u0447\u0435\u0440\u0435\u0437 WiFi:<\/p>\n<div class=\"tm-iframe_temp\" data-src=\"https:\/\/embedd.srv.habr.com\/iframe\/684088bca54631a83a9e93a8\" data-style=\"\" id=\"684088bca54631a83a9e93a8\" width=\"\"><\/div>\n<p><a class=\"anchor\" name=\"the-end\" id=\"the-end\"><\/a><\/p>\n<h2>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u043f\u0438\u043b\u043e\u0433\u0430<\/h2>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b, \u043a\u0430\u043a \u0441 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0432\u0435\u0431-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c RESTful API-\u0441\u0435\u0440\u0432\u0435\u0440 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043d\u0430 Unreal Engine. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u043e HTTP, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0448\u0438\u0440\u043e\u043a\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u043d\u0451\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u043a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u0438.<\/p>\n<p>\u041a\u043e\u0440\u043e\u0442\u0435\u043d\u044c\u043a\u0430\u044f \u0432\u044b\u0436\u0438\u043c\u043a\u0430. \u042f \u043f\u043e\u043f\u044b\u0442\u0430\u043b\u0441\u044f \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b:<\/p>\n<ul>\n<li>\n<p>\u043a\u0430\u043a \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 Unreal Engine \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043b\u043e\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e, \u043d\u043e \u043c\u043e\u0449\u043d\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f HTTPServer;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0441 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0435\u0439 endpoint&#8217;\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 ini-\u0444\u0430\u0439\u043b;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u0430\u043a \u0432 C++, \u0442\u0430\u043a \u0438 \u0432 Blueprint;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 HTTP;<\/p>\n<\/li>\n<li>\n<p>\u043a\u0430\u043a \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0438\u0435\u043d\u0442\u0430-\u0433\u0435\u0439\u043c\u043f\u0430\u0434 \u043d\u0430 .NET MAUI.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0434\u0445\u043e\u0434 \u0432\u0437\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0447\u0435\u0440\u0435\u0437 HTTP \u0445\u043e\u0440\u043e\u0448 \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u043d\u0438\u044f \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0441\u0446\u0435\u043d\u044b \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u044f\u0436\u0451\u043b\u044b\u0445 RPC-\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 UE. \u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043b\u0451\u0433\u043a\u043e\u0439, \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0438 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u043e\u0439 \u043a\u0430\u043a \u0434\u043b\u044f \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u0442\u0430\u043a \u0438 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u2014 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u0444\u0435\u0440\u0435 \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0439, \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0432\u0441\u0435\u0433\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e \u0432\u0430\u0448\u0435\u0439 \u0434\u0443\u0448\u0435 \u0443\u0433\u043e\u0434\u043d\u043e, \u0438 \u043d\u0430 \u0447\u0442\u043e \u0432\u0430\u0448\u0435\u0439 \u0444\u0430\u043d\u0442\u0430\u0437\u0438\u0438 \u0445\u0432\u0430\u0442\u0438\u0442.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441 \u0432\u0430\u0448\u0438\u043c UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c \u2014 \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 \u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043c\u043e\u0433\u0443\u0442 \u0440\u0435\u0448\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u0434\u0430\u0447 \u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0412\u0441\u0451 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0435 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u0445:<\/p>\n<ul>\n<li>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d HttpServerPlugin:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpServerPlugin\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerPlugin<\/a><\/p>\n<\/li>\n<li>\n<p>\u0414\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 UE:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpServerDemo\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerDemo<\/a><\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442-\u0433\u0435\u0439\u043c\u043f\u0430\u0434:\u00a0<a href=\"https:\/\/github.com\/lpestl\/HttpGamepadInput\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpGamepadInput<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0442\u0430\u0442\u044c\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0439 \u2014 \u0441\u0442\u0430\u0432\u044c\u0442\u0435\u00a0<s>\u043b\u0430\u0439\u043a<\/s>\u00a0\u0437\u0432\u0435\u0437\u0434\u043e\u0447\u043a\u0443 \u043d\u0430 GitHub. \u041a\u0440\u0438\u0442\u0438\u043a\u0430 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 &#8212; \u043f\u0440\u0438\u0432\u0435\u0442\u0441\u0432\u0443\u0435\u0442\u0441\u044f!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/915746\/\"> https:\/\/habr.com\/ru\/articles\/915746\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u043e \u043c\u043d\u043e\u0439 \u0432\u0441\u0442\u0430\u043b\u0430 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430: \u043e\u0440\u0433\u0430\u043d\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 Unreal Engine \u0441 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e: \u043d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 Unreal Engine (\u043d\u0430\u0437\u043e\u0432\u0451\u043c \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u0435\u0439), \u0430 \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043d\u0430 \u044d\u0442\u0443 \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044e. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0430\u043a \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u043c\u0443\u043b\u044c\u0442\u0438\u043c\u0435\u0434\u0438\u0439\u043d\u0430\u044f \u0438\u043d\u0441\u0442\u0430\u043b\u043b\u044f\u0446\u0438\u044f \u0443\u0440\u043e\u0432\u043d\u044f\u00a0<a href=\"https:\/\/youtu.be\/vib8cg4IFUc?si=W1ujuoAHuQ8JHHmB\" rel=\"noopener noreferrer nofollow\">\u0437\u043c\u0435\u0439\u043a\u0430 \u043d\u0430 \u0444\u0430\u0441\u0430\u0434\u0435 \u0437\u0434\u0430\u043d\u0438\u044f<\/a>, \u0442\u0430\u043a \u0438 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u2014 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u044b\u043c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c \u0441 \u0442\u0435\u043b\u0435\u0444\u043e\u043d\u0430, \u043a\u0430\u043a \u0441 \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0440\u0435\u0432\u044c\u044e\u0448\u043a\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0437\u0434\u0435\u0441\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u2013\u0441\u0435\u0440\u0432\u0435\u0440. \u041e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u0432\u0430\u0436\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435: \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b Unreal Engine, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a RPC \u0438\u043b\u0438 \u0440\u0435\u043f\u043b\u0438\u043a\u0430\u0446\u0438\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0441\u0442\u0435\u043a \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b. \u041d\u043e \u0438 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043b\u0438\u0448\u043d\u0438\u0445 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043d\u044b\u0445 \u043f\u0440\u043e\u0441\u043b\u043e\u0435\u043a \u0432 \u0432\u0438\u0434\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u0435\u0431 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \/ \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u043d\u0430 \u043a\u0430\u043a\u043e\u043c-\u0442\u043e \u0435\u0449\u0451 \u043e\u0434\u043d\u043e\u043c \u0441\u0442\u0435\u043a\u0435 &#8212; \u043d\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044f \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044e \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 Unreal Engine \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 HTTP-\u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0430 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438, \u0432 \u0446\u0435\u043b\u043e\u043c, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0441 UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438.<\/p>\n<h2>\u041e \u0447\u0451\u043c \u043f\u043e\u0439\u0434\u0451\u0442 \u0440\u0435\u0447\u044c<\/h2>\n<ol>\n<li>\n<p><a href=\"https:\/\/scheme\" rel=\"noopener noreferrer nofollow\">\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/what-in-engine\" rel=\"noopener noreferrer nofollow\">\u0427\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0434\u0432\u0438\u0436\u043a\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/a>?<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/wrapper\" rel=\"noopener noreferrer nofollow\">\u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f HTTPServer<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/character-control\" rel=\"noopener noreferrer nofollow\">\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/client-gamepad\" rel=\"noopener noreferrer nofollow\">\u041f\u0438\u0448\u0435\u043c \u043a\u043b\u0438\u0435\u043d\u0442-Gamepad<\/a><\/p>\n<\/li>\n<\/ol>\n<p><a href=\"https:\/\/the-end\" rel=\"noopener noreferrer nofollow\">\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u043f\u0438\u043b\u043e\u0433\u0430<\/a><\/p>\n<p><a class=\"anchor\" name=\"scheme\" id=\"scheme\"><\/a><\/p>\n<h3>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/h3>\n<p>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<ul>\n<li>\n<p>\u043d\u0430 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u043f\u0440\u043e\u0435\u043a\u0442 Unreal Engine, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0435\u0441\u0442\u044c \u0438\u0433\u0440\u043e\u0432\u0430\u044f \u0441\u0446\u0435\u043d\u0430 \u0441 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u043c. HTTP-\u0441\u0435\u0440\u0432\u0435\u0440, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u0443\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432 \u0441\u0446\u0435\u043d\u0435;<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435-\u0433\u0435\u0439\u043c\u043f\u0430\u0434, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0435 \u0441\u043e\u0431\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 HTTP \u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043e\u0434\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0435\u0442\u0438 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u0447\u0435\u0440\u0435\u0437 Wi-Fi, \u0432 \u0447\u0430\u0441\u0442\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u043e \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u044b \u043a \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442\u0443 \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u043c \u0433\u0435\u0439\u043c\u043f\u0430\u0434\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f HTTP-\u0437\u0430\u043f\u0440\u043e\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 UE-\u043f\u0440\u043e\u0435\u043a\u0442\u0430. Unreal Engine \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441, \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u0435\u0433\u043e \u043a\u0430\u043a \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0443\u044e \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0430 \u0432 \u0441\u0446\u0435\u043d\u0435.<\/p>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u043e\u0433\u043e \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0438\u0433\u0440\u043e\u0432\u044b\u043c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 HTTP-\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 RPC-\u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0438\u043b\u0438 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u041a\u043e\u043d\u0446\u0435\u043f\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u043a\u0430<\/figcaption><\/div>\n<\/figure>\n<p><a class=\"anchor\" name=\"what-in-engine\" id=\"what-in-engine\"><\/a><\/p>\n<h3>\u0427\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0434\u0432\u0438\u0436\u043a\u0435 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/h3>\n<p>Unreal Engine \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0448\u0438\u0440\u043e\u043a\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u043c\u043e\u0434\u0443\u043b\u0435\u0439 \u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043c\u043d\u043e\u0433\u0438\u0435 \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0448\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u00ab\u0438\u0437 \u043a\u043e\u0440\u043e\u0431\u043a\u0438\u00bb. \u041a\u043e\u0433\u0434\u0430 \u0440\u0435\u0447\u044c \u0437\u0430\u0445\u043e\u0434\u0438\u0442 \u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 UE-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0443 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0435\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0439. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0438\u0437 \u043d\u0438\u0445:<\/p>\n<ol>\n<li>\n<p>\u041c\u043e\u0434\u0443\u043b\u044c\u00a0<code>Sockets<\/code>\u00a0\u042d\u0442\u043e \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0439 API \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u043e\u043a\u0435\u0442\u0430\u043c\u0438, \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0435 \u0440\u0430\u0437\u043b\u0438\u0447\u0438\u044f. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0436\u043d\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c HTTP-\u0441\u0435\u0440\u0432\u0435\u0440 \u2014 \u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 TCP-\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0434\u043e \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 HTTP-\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432. \u0422\u0430\u043a\u043e\u0439 \u043f\u043e\u0434\u0445\u043e\u0434 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c, \u043d\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0442\u0440\u0430\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u043d \u043f\u043e\u0434\u043e\u0439\u0434\u0451\u0442 \u0442\u0435\u043c, \u043a\u043e\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c, \u043d\u043e \u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u044b\u0445 MVP \u0438\u043b\u0438 \u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043e\u0434\u0443\u043b\u044c\u00a0<code>Runtime\/Online\/HTTPServer<\/code>\u00a0\u041f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u0432 Unreal Engine \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0441 \u0432\u0435\u0440\u0441\u0438\u0438 4.25 (c \u043c\u0430\u044f 2019). \u042d\u0442\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c REST-\u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u0440\u044f\u043c\u043e \u0432\u043d\u0443\u0442\u0440\u0438 UE \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438 \u0432\u0440\u043e\u0434\u0435 Node.js, Python \u0438\u043b\u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0441\u043a\u0443\u0434\u043d\u0443\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u043e\u043d \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0445 \u0438 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 API, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u041f\u041e.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043b\u0430\u0433\u0438\u043d\u00a0<code>RemoteControl<\/code>\u00a0\u0422\u0430\u043a\u0436\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0432 2019 \u0433\u043e\u0434\u0443 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u0445 HTTPServer. \u041f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 \u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438 \u0432 \u0441\u0446\u0435\u043d\u0435 \u0447\u0435\u0440\u0435\u0437 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b.\u00a0<code>RemoteControlAPI<\/code>\u00a0\u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0430\u043a\u0442\u043e\u0440\u0430\u043c, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0438 \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c. \u041e\u0434\u043d\u0430\u043a\u043e \u0443 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0437\u043d\u0430\u0442\u044c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0446\u0435\u043d\u044b, \u0438\u043c\u0435\u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0438\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0447\u0442\u043e \u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u043f\u0440\u0438 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0435\u043c\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0421\u0440\u0430\u0432\u043d\u0438\u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u043e\u043f\u0446\u0438\u0438, \u044f \u043f\u0440\u0438\u0448\u0451\u043b \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e \u043d\u0430\u0438\u043b\u0443\u0447\u0448\u0438\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u0432 \u043c\u043e\u0451\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u043c\u043e\u0434\u0443\u043b\u044c\u00a0<code>HTTPServer<\/code>. <s>\u041e\u043d \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 \u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0432\u043e\u0431\u043e\u0434\u0443 \u0432 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0438<\/s>. \u041e\u043d \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043c\u0435\u043d\u044c\u0448\u0438\u0445 \u0442\u0435\u043b\u043e\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0439, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. <\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043e\u0431\u0451\u0440\u0442\u043a\u0443, \u0443\u043f\u0440\u043e\u0449\u0430\u044e\u0449\u0443\u044e \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u044e, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e \u043e\u0442\u0432\u0435\u0442\u043e\u0432, \u0438\u0437\u0431\u0430\u0432\u043b\u044f\u044f \u043e\u0442 \u0440\u0443\u0442\u0438\u043d\u044b \u0438 \u0443\u0441\u043a\u043e\u0440\u044f\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443. \u042d\u0442\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0433\u0438\u0431\u043a\u0438\u043c, \u043b\u0451\u0433\u043a\u0438\u043c \u0432 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u2014 \u043e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0446\u0435\u043d\u043e\u0439 \u0434\u043e \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0443\u0434\u0430\u043b\u0451\u043d\u043d\u044b\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<p><a class=\"anchor\" name=\"wrapper\" id=\"wrapper\"><\/a><\/p>\n<h2> \u041e\u0431\u0451\u0440\u0442\u043a\u0430 \u0434\u043b\u044f HTTPServer  <\/h2>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 RESTful API \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u043c\u043d\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0435\u0441\u043b\u0438 \u043d\u0430\u0431\u043e\u0440 endpoints \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 \u043a\u043e\u043d\u0444\u0438\u0433, \u0442\u0435\u043c \u0441\u0430\u043c\u044b\u043c \u0443\u0431\u0438\u0440\u0430\u044f \u0438\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 UE \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u043c. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0434\u043b\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0433\u043e\u00a0<code>HTTPServer<\/code>\u00a0\u043c\u043e\u0434\u0443\u043b\u044f \u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u043b \u0435\u0451 \u0432 \u043f\u043b\u0430\u0433\u0438\u043d \u043d\u0430 GitHub:  <\/p>\n<p><a href=\"https:\/\/github.com\/lpestl\/HttpServerPlugin\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/lpestl\/HttpServerPlugin<\/a><\/p>\n<p>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u0441\u0442\u044b\u043c, \u043b\u0435\u0433\u043a\u043e \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u043c \u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 MVP. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043b\u0430\u0433\u0438\u043d, \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u2014 \u0438 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044f \u043a\u0430\u043a \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0435, \u0442\u0430\u043a \u0438 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b. \u0415\u0441\u043b\u0438 \u0432\u0430\u0441 \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u044f\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u044d\u0442\u043e\u0442 \u0440\u0430\u0437\u0434\u0435\u043b \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u043f\u0443\u0441\u0442\u0438\u0442\u044c. <\/p>\n<p>\u0414\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u0441\u0442\u0430\u0434\u0438\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0451\u043c\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u0441\u0451 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u0436\u0435 \u0447\u0435\u0440\u0435\u0437 Blueprint.<\/p>\n<p>\u0414\u043b\u044f \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443\u00a0<code>FEndpointData<\/code>\u00a0\u0438 \u043a\u043b\u0430\u0441\u0441\u00a0<code>UHttpServerSettings<\/code>, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u0443\u0434\u043e\u0431\u043d\u0443\u044e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0438 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432:<\/p>\n<pre><code class=\"cpp\">USTRUCT(BlueprintType) struct HTTPSERVERWRAPPERMODULE_API FEndpointData { GENERATED_BODY()  UPROPERTY(EditAnywhere, BlueprintReadWrite) FString Endpoint {};  UPROPERTY(EditAnywhere, BlueprintReadWrite) EHttpServerWrapperRequestVerbs Verbs {}; };     UCLASS(DisplayName=\"HTTP Server Settings\", Config = \"HttpServer\", DefaultConfig) class HTTPSERVERWRAPPERMODULE_API UHttpServerSettings : public UDeveloperSettings { GENERATED_BODY()  public:     \/*     Something else     *\/  private: UPROPERTY(meta = (AllowPrivateAccess = \"true\"), Config, EditAnywhere, BlueprintReadOnly, Category = \"General\") int32 Port { 8080 };  UPROPERTY(meta = (AllowPrivateAccess = \"true\"), Config, EditAnywhere, BlueprintReadOnly, Category = \"General\") TArray&lt;FEndpointData&gt; Endpoints {}; };<\/code><\/pre>\n<p>\u041e\u0444\u043e\u0440\u043c\u043b\u0435\u043d\u0438\u0435\u00a0<code>UHttpServerSettings<\/code>\u00a0\u043a\u0430\u043a \u043f\u043e\u0442\u043e\u043c\u043a\u0430\u00a0<code>UDeveloperSettings<\/code>\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043f\u0440\u044f\u043c\u043e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435:\u00a0<code>UnrealEditor \u2192 Project Settings<\/code>:  <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043f\u043b\u0430\u0433\u0438\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e HTTP-\u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u2014 \u043e\u043d \u043f\u043e\u043c\u0435\u0447\u0435\u043d \u043a\u0430\u043a BlueprintType, Blueprintable, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043d\u0435\u0439 \u0432 \u0431\u043b\u044e\u043f\u0440\u0438\u043d\u0442\u0430\u0445.  <\/p>\n<pre><code class=\"cpp\">UCLASS(BlueprintType, Blueprintable) class HTTPSERVERWRAPPERMODULE_API UHttpServer : public UObject<\/code><\/pre>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u2014 \u0437\u0430\u043f\u0443\u0441\u043a \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0430:  <\/p>\n<pre><code class=\"cpp\">UFUNCTION(BlueprintCallable, Category = \"HttpServer\") void StartApiServer();  UFUNCTION(BlueprintCallable, Category = \"HttpServer\") void StopApiServer();<\/code><\/pre>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0443 \u0432\u0441\u0435\u0445 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0435 endpoint&#8217;\u043e\u0432 \u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0443, \u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u2014 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0443\u044e \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u043e\u0432. \u0412\u0441\u0451 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043e \u0447\u0435\u0440\u0435\u0437:  <\/p>\n<pre><code class=\"cpp\">\/\/~~~ HEADER ~~~  \/\/ \u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432 \u043a\u043b\u0430\u0441\u0441 \u0432 HEADER private: \/** Http router handle *\/ TSharedPtr&lt;IHttpRouter&gt; HttpRouter;  \/** Mapping of routes to delegate handles *\/ TMap&lt;FString, FHttpRouteHandle&gt; ActiveRouteHandles;  \/\/~~~ CPP ~~~  \/\/ \u0418 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0443 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \"\u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439\" (\u0437\u0430\u043f\u0443\u0441\u043a \u0441\u0430\u043c\u043e\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430) void UHttpServer::StartApiServer() { FHttpServerModule&amp; HttpServerModule = FHttpServerModule::Get();      \/\/ \u0411\u0435\u0440\u0451\u043c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438\/\u043a\u043e\u043d\u0444\u0438\u0433 UHttpServerSettings* Settings = UHttpServerSettings::Get(); if (IsValid(Settings)) { if (HttpRouter) { HttpRouter.Reset(); } HttpRouter = FHttpServerModule::Get().GetHttpRouter(Settings-&gt;GetPort(), \/* bFailOnBindFailure = *\/ true); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"Starting HttpServer on %d port:\"), Settings-&gt;GetPort());  TArray&lt;FEndpointData&gt; Endpoints = Settings-&gt;GetEndpoints(); for (FEndpointData&amp; EndpointData : Endpoints) { FHttpPath EndpointPath = EndpointData.Endpoint; EHttpServerRequestVerbs Verbs = static_cast&lt;EHttpServerRequestVerbs&gt;(EndpointData.Verbs);  ActiveRouteHandles.Add( EndpointData.Endpoint,                 \/* \u0422\u0443\u0442 \u0441\u043e\u0437\u0434\u0430\u0451\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0447\u0438\u043a HTTP \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0431 Endpoint *\/ HttpRouter-&gt;BindRoute( EndpointPath, Verbs, FHttpRequestHandler::CreateUObject(this, &amp;UHttpServer::HandleRequest, EndpointData) ) ); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"\\t%s: %s \"), *StaticEnum&lt;EHttpServerWrapperRequestVerbs&gt;()-&gt;GetNameStringByValue(static_cast&lt;int64&gt;(EndpointData.Verbs)), *EndpointData.Endpoint); }          \/\/ \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 HttpServerModule.StartAllListeners(); } }  \/\/ \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0443\u0436\u043d\u043e \u043d\u0435 \u0437\u0430\u0431\u044b\u0442\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0435\u0440 void UHttpServer::StopApiServer() {     \/\/ \u0415\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0434\u0432\u0438\u0436\u043a\u043e\u0432\u044b\u0439 HTTP Server \u043c\u043e\u0434\u0443\u043b\u044c if (FHttpServerModule::IsAvailable()) {         FHttpServerModule&amp; HttpServerModule = FHttpServerModule::Get();         \/\/ \u0421\u0442\u043e\u043f\u0430\u0435\u043c \u0441\u043b\u0443\u0448\u0430\u0442\u0435\u043b\u0435\u0439 HttpServerModule.StopAllListeners();  UHttpServerSettings* Settings = UHttpServerSettings::Get(); if (IsValid(Settings)) { TArray&lt;FEndpointData&gt; Endpoints = Settings-&gt;GetEndpoints(); UE_LOG(LogHttpServerPlugin, Log, TEXT(\"Unbound endpoints:\")); \/\/ \u041f\u0440\u043e\u0439\u0434\u0451\u043c \u043f\u043e \u0432\u0441\u0435\u043c \"\u043d\u0430\u043a\u043e\u043d\u0444\u0438\u0436\u0435\u043d\u043d\u044b\u043c\" \u0435\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430\u043c for (FEndpointData&amp; EndpointData : Endpoints) { if (ActiveRouteHandles.Find(EndpointData.Endpoint) != nullptr) { if (ActiveRouteHandles[EndpointData.Endpoint].IsValid()) { UE_LOG(LogHttpServerPlugin, Log, TEXT(\"\\t* %s\"), *EndpointData.Endpoint);                         \/\/ \u0418 \u043e\u0442\u043f\u0438\u0448\u0435\u043c\u0441\u044f \u043e\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 HttpServerModule.GetHttpRouter(Settings-&gt;GetPort())-&gt;UnbindRoute(ActiveRouteHandles[EndpointData.Endpoint]); } } } } ActiveRouteHandles.Reset(); }  if (HttpRouter) {<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-462119","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462119","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=462119"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/462119\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=462119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=462119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=462119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}