{"id":326943,"date":"2022-01-10T08:41:56","date_gmt":"2022-01-10T08:41:56","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=326943"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=326943","title":{"rendered":"<span>\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f Unity3d. \u0427\u0430\u0441\u0442\u044c 3<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\" class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e \u0412\u0430\u0441, \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0435 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438. \u0412 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0432 \u0441\u0435\u0440\u0438\u0438 \u043e \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043b\u043e\u0433\u0438\u043a\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435. \u0414\u0430\u043d\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0446\u0435\u043b\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0438 \u043e\u0431\u0448\u0438\u0440\u043d\u044b\u043c, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u043f\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u043a\u0430\u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0432\u044f\u0437\u0435\u0439, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 \u0438 \u0442. \u043f. <\/p>\n<p>\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 \u0441\u0435\u0440\u0438\u0438:<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/448190\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f Unity3d. \u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/466187\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f Unity3d. \u0427\u0430\u0441\u0442\u044c 2<\/a><\/p>\n<h2>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"464\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ec2\/46a\/a1d\/ec246aa1dad070528eb18ad6bc7f7991.png\" data-width=\"929\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u0447\u0442\u043e \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0432\u0430\u0436\u043d\u043e\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u0441 <strong>Unity<\/strong>. \u042f \u0434\u0443\u043c\u0430\u044e, \u043c\u043d\u043e\u0433\u0438\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043e\u0431 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f <strong>Unity3D<\/strong>, \u043d\u043e \u044f \u0432\u0441\u0435 \u0436\u0435 \u043e\u043f\u0438\u0448\u0443 \u0438\u0445:<\/p>\n<ol>\n<li>\n<p>\u041e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0447\u0435\u043d\u044c \u043a\u0440\u0438\u0432\u0430\u044f \u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 (<strong>Coroutine<\/strong>).<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0430 \u0435\u0441\u0442\u044c, \u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u0438\u0441\u0430\u043b\u0441\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440, \u0435\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e<\/em>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u043a\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u043a\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 <strong>Unity3d.<\/strong><\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u044d\u0442\u0438 \u0434\u0432\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432. <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<ul>\n<li>\n<p><strong>VLELogicEditor<\/strong>. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043e\u043a\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438<\/p>\n<ul>\n<li>\n<p><strong>MainMenu<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u043d\u044e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>LogicArea<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Status<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>VLECatalog<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u0441\u0431\u043e\u0440\u0430 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEInspector<\/strong>. \u041a\u043b\u0430cc, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 <strong>Unity3D<\/strong><\/p>\n<ul>\n<li>\n<p><strong>VLELogicComponentCustomEditor<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>VLEObjectEditor<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b <strong>Unity3d<\/strong>. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u044d\u0442\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 <strong>VLObject<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>VLESettingWindow<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u043a\u043d\u0430 \u043e\u0431\u0449\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>VLESearchWindow<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0438\u0441\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0433\u0440\u0443\u043f\u043f \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEWidget<\/strong>. \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<ul>\n<li>\n<p><strong>VLEComponent<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEGroup<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0440\u0443\u043f\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>VLELink<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>VLEVariable<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u0447\u0442\u043e \u0433\u0434\u0435 \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"947\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/020\/bc4\/de8\/020bc4de8c2d05dc8331792f8185fa4b.png\" data-width=\"1865\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0443\u043d\u043a\u0442\u0430\u0445.<\/p>\n<h2>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0432 \u044f\u0434\u0440\u0435<\/h2>\n<p>\u0412 \u0445\u043e\u0434\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0434\u043b\u044f \u0435\u0433\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439 \u0432 \u044f\u0434\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 <strong>Unity3D<\/strong>. \u0421 \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u0431\u044b\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u0434, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043d\u0438\u0436\u0435. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u044f\u0434\u0440\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u044f\u0434\u0440\u043e \u0434\u043b\u044f \u0431\u0438\u043b\u0434\u0430 \u0431\u044b\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u043f\u0440\u0435\u0434\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 <em>UNITY_EDITOR<\/em>.<\/p>\n<h3>\u0421\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0441\u0446\u0435\u043d\u0435<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0441\u0446\u0435\u043d\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0433\u0434\u0435-\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0445 \u0438\u043c\u0435\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0442\u0435\u043c \u0431\u044b\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435.<\/p>\n<p>\u0421 \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u0434\u043b\u044f \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441 <strong>LogicController<\/strong> \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR public string[] LogicVisualNames => SceneLogicList.ConvertAll(item => item.Name).ToArray();\u00a0\u00a0\u00a0\u00a0\u00a0  #endif<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"145\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/f48\/af8\/e22\/f48af8e2293a2f4e3f2a6b0a35d2fa5c.png\" data-width=\"924\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p>\u0412 \u0445\u043e\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 \u0446\u0435\u043b\u044c\u044e \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0431\u0438\u043b\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0440\u0430\u043d\u0435\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR  public IDictionary&lt;string, LogicComponent> RuntimeComponentInstances = new Dictionary&lt;string, LogicComponent>(); #endif<\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0432 \u044d\u0442\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR foreach (var componentInstance in instances) { RuntimeComponentInstances.Add(componentInstance.Key, componentInstance.Value); } #endif<\/code><\/pre>\n<h3>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity<\/h3>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043d\u0430\u0434 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 <strong>Unity<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>VLObject<\/strong>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0440\u044f\u0434 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u0435\u0440\u0436\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 <strong>Unity<\/strong> \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u043a\u044d\u0448\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>ObjectLinkData<\/strong> \u0437\u0430\u0432\u0435\u0434\u0435\u043c \u043f\u043e\u043b\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR public int Holders; #endif<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432 \u0431\u0438\u043b\u0434\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity \u043f\u043e \u0441\u0443\u0442\u0438 \u0441\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b, \u0442\u043e \u0442\u0430\u043c \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0445 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437\u0432\u043d\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0441\u0430\u043c\u043e\u0439 \u0441\u043e\u0431\u043e\u0439 \u044d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0443\u0436\u0435\u043d, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432:<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">#if UNITY_EDITOR public string SetObject(string oldObjId, UnityEngine.Object newObj) {                   if (newObj == null)   {     RemoveObjectLink(oldObjId);      return string.Empty;   }   else   {     var linkData = _objectLinks.Find(link => link.Obj == newObj);                      if (linkData == null)                         {         linkData = new ObjectLinkData(Guid.NewGuid().ToString(), newObj);                            _objectLinks.Add(linkData);     }else     {       linkData.Holders++;        if (linkData.Id != oldObjId)       {           RemoveObjectLink(oldObjId);       }     }                                                                  return linkData.Id;   } }          private void RemoveObjectLink(string objectId) {     var linkData = _objectLinks.Find(link => string.Compare(link.Id, objectId, StringComparison.Ordinal) == 0);                if (linkData != null)   {     linkData.Holders--;        if (linkData.Holders &lt;= 0)       {       _objectLinks.Remove(linkData);       }     }   } #endif<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u043f\u043e \u043a\u043e\u0434\u0443, \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u0435\u0440\u0436\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u0438.<\/p>\n<h2>\u0420\u0438\u0441\u0443\u0435\u043c \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430<\/h2>\n<h3>\u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430<\/h3>\n<p>\u0421 \u0446\u0435\u043b\u044c\u044e \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"cs\">public interface IEditorDrawer { bool Draw(Rect container, bool lockInput); } <\/code><\/pre>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0438\u043a\u043b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 (<strong>OnGUI<\/strong> \u043c\u0435\u0442\u043e\u0434) \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">if (!EditorApplication.isCompiling) {     for (var i = 0; i &lt; _currentEditorDraw.Count; i++)     {         var editorDraw = _currentEditorDraw[i];          _inputLocked = editorDraw.Draw(position, _inputLocked);     }      RemoveInactiveEditorDraws();  _inputLocked = false; } else {     GUI.Label(new Rect(5f, 5f, position.width - 10f, 25f), \"wait for compiling...\"); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e, \u0435\u0441\u043b\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b <strong>IEditorDraw<\/strong> \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>Rect<\/strong> \u043e\u043a\u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0444\u043b\u0430\u0433\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0432\u0432\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 <strong>true<\/strong> \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0438\u0445 \u043e\u043a\u043e\u043d (\u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0438 \u0442.\u043f.) \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0438\u0437 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430, \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <strong>DrawEditor<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void DrawEditor(IEditorDrawer drawEditor) { if (!_currentEditorDraw.Contains(drawEditor))   {   _currentEditorDraw.Add(drawEditor);   }else   {   _currentEditorDrawForDelete.Add(drawEditor);   }             }<\/code><\/pre>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u043a\u043d\u043e \u0443\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, \u0442\u043e \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0436\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>RemoveInactiveEditorDraws<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void RemoveInactiveEditorDraws() { if (_currentEditorDrawForDelete.Count > 0) { for (var i = 0; i &lt; _currentEditorDrawForDelete.Count; i++) { var editorDraw = _currentEditorDrawForDelete[i];  (editorDraw as IDisposable)?.Dispose();  _currentEditorDraw.Remove(editorDraw); }                  _currentEditorDrawForDelete.Clear(); } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0421\u043e\u0431\u044b\u0442\u0438\u044f<\/h3>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0438\u0437 C# &#8212; <strong>event\/delegate<\/strong>. \u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u0438. \u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432\u0441\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><strong>SelectedComponentChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>SelectedLogicChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>SelectedLogicUpdated<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ComponentActiveChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>OpenLogicsStorage<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u0435\u0441\u043b\u0438 \u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0438 <strong>UI<\/strong> \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043d\u0430\u0436\u0430\u0442\u0438\u044f, <strong>drag&amp;drop<\/strong> \u0438 \u0442. \u043f.). \u0412 \u0432\u0438\u0434\u0443 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0440\u0435\u043d\u0434\u0435\u0440 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439, \u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u043a\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u0430 \u0441 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043c \u0436\u0435, \u0433\u0434\u0435 \u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u043e \u0432\u0441\u0435\u043c, \u0442\u043e \u043e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e (\u043d\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0432\u0438\u0434\u0436\u0435\u0442\u0430\u043c\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u0432\u043e\u043c <strong>Unity UI<\/strong>).<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 Event.Use() \u0438 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f EventType.Used, \u043e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0431\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/em><\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0438\u0432\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>IEditorDraw<\/strong> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u043b\u0430\u0433\u0430 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0432\u043e\u0434 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c\/\u043e\u043a\u043d\u043e\u043c. <\/p>\n<h3>\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b<\/h3>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"31\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/851\/0eb\/01e\/8510eb01e16bdfbbc0aa3ac0768518b0.png\" data-width=\"908\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043c\u0435\u043d\u044e:<\/p>\n<pre><code class=\"cs\">private class MainMenuToolbar : IEditorDrawer, IDisposable {}<\/code><\/pre>\n<p>\u0418\u043a\u043e\u043d\u043a\u0438 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 (\u0438\u0437 <strong>Unity<\/strong>) \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <strong>EditorGUIUtility.IconContent<\/strong>:<\/p>\n<pre><code class=\"cs\">_catalogIconContent = new GUIContent(EditorGUIUtility.IconContent(\"project\"));<\/code><\/pre>\n<p>\u0421\u0430\u043c\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0440\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e <strong>GUILayout.Button<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0435\u0440\u043d\u0443\u0442 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private bool LayoutButton(GUIContent content, string tooltip = \"\", bool state = true) { EditorGUI.BeginDisabledGroup(!state);    content.tooltip = tooltip;  var result = GUILayout.Button(content, _buttonStyle, GUILayout.MaxWidth(_mainMenuHeightBar - 5f), GUILayout.MaxHeight(_mainMenuHeightBar - 5f));    EditorGUI.EndDisabledGroup();  if (!_lockInput) { return result; }else { return false; } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0434\u0440\u0443\u0433\u0438\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u043c\u043e\u0433\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u0432 \u043a\u043d\u043e\u043f\u043a\u0438, \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>MainMenuToolbar<\/strong> \u0441\u043e\u0437\u0434\u0430\u043d \u043d\u0430\u0431\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public event SaveLogicEvent OnSaveLogic; public event AddLogicToSceneEvent OnAddLogicToScene; public event CreateLogicEvent OnCreateLogic; public event DeleteLogicEvent OnDeleteLogic; public event RestoreSceneLogicEvent OnRestoreSceneLogic; public event LoadLogicEvent OnLoadLogic; public event SearchComponentEvent OnSearchComponent; public event CollapseComponentEvent OnCollapseComponent; public event CollapseParameterEvent OnCollapseParameter; public event RollbackLogicEvent OnRollbackLogic;<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438 \u043e\u0442\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0432\u044b\u043d\u043e\u0441\u0438\u0442\u0441\u044f \u0442\u0443\u0434\u0430, \u0433\u0434\u0435 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u041e\u0434\u043d\u0430\u043a\u043e \u044f \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u043b \u044d\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0442\u043f\u0438\u0441\u043a\u0430 \u043e\u0442 \u0432\u0441\u0435\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043c, \u0433\u0434\u0435 \u043e\u043d\u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f (\u043a\u0430\u043a \u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u043c\u0435\u0442\u043e\u0434e <strong>Dispose<\/strong>). \u0414\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">if (OnSaveLogic != null) { foreach (var eventHandler in OnSaveLogic.GetInvocationList()) { OnSaveLogic -= (SaveLogicEvent)eventHandler; } }<\/code><\/pre>\n<h4>\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0438<\/h4>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"457\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/66a\/08c\/63d\/66a08c63dd029b7694734f9c059c7c10.png\" data-width=\"908\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u0432\u0438\u0434\u0436\u0435\u0442\u0430 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438:<\/p>\n<pre><code class=\"cs\">private class LogicArea : LogicBaseDrawer, ILogic, IDisposable{}<\/code><\/pre>\n<p><strong>LogicBaseDrawer<\/strong> \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u0430\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>IEditorDrawer<\/strong>. <strong>ILogic<\/strong> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code>public interface ILogic { Rect RealArea { get; } Rect ViewArea { get; } Vector2 ScrollPosition { get; }              void CenterToComponent(ILogicWidget component); void Reset(); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<ul>\n<li>\n<p><strong>RealArea<\/strong> \u2013 \u044d\u0442\u043e \u043e\u0431\u0449\u0438\u0439 <strong>Rect<\/strong> \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><strong>ViewArea<\/strong> \u2013 \u044d\u0442\u043e \u0432\u0438\u0434\u0438\u043c\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430<\/p>\n<\/li>\n<li>\n<p><strong>CenterToComponent<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0439 \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432 \u043e\u043a\u043d\u0435 \u043f\u043e\u0438\u0441\u043a\u0430)<\/p>\n<\/li>\n<li>\n<p><strong>Reset<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0431\u0440\u0430\u0441\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0438\u0441\u0443\u0435\u0442 \u043e\u043a\u043d\u043e \u043b\u043e\u0433\u0438\u043a\u0438 \u044d\u0442\u043e:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u0438<\/p>\n<\/li>\n<li>\n<p>\u0413\u0440\u0443\u043f\u043f\u044b<\/p>\n<\/li>\n<\/ul>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u044d\u0442\u0438\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435:<\/p>\n<pre><code class=\"cs\">private readonly IList&lt;IWidgetGroup> _logicGroups; private readonly IList&lt;ILogicWidget> _logicWidgets; private readonly IList&lt;ILink> _logicLinks;<\/code><\/pre>\n<p>\u041e\u0431\u0449\u0438\u0439 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"cs\">protected override void LogicDraw(bool lockInput) { DrawLinks(lockInput); DrawWidgets(lockInput); DrawGroups(lockInput); DrawSelectedWidgets(lockInput); DrawSelectedLinkData(); DrawSelectionRect(); }<\/code><\/pre>\n<p>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u0430\u043a\u043e\u0439:<\/p>\n<ol>\n<li>\n<p>\u0420\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u0438<\/p>\n<\/li>\n<li>\n<p>\u0420\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0420\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0433\u0440\u0443\u043f\u043f\u044b<\/p>\n<\/li>\n<li>\n<p>\u0420\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0420\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438<\/p>\n<\/li>\n<li>\n<p>\u0420\u0438\u0441\u0443\u0435\u0442\u0441\u044f <strong>Rect<\/strong> \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432\/\u0441\u0432\u044f\u0437\u0435\u0439<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u043a\u043b\u0430\u0441\u0441 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0435 \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0439 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u043e\u0439, \u0430 \u043b\u0438\u0448\u044c \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/em><\/p>\n<p>\u0414\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u0430\u043c\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u043d\u0430\u0431\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public event AddComponentEvent OnAddComponent; public event RemoveComponentEvent OnRemoveComponent; public event CopyComponentEvent OnCopyComponent; public event AddLinkEvent OnAddLink; public event PasteComponentEvent OnPasteComponent; public event SelectAllEvent OnSelectAllEvent; public event AddGroupEvent OnAddGroupEvent; public event UngroupEvent OnUngroupEvent; public event FindEvent OnFindEvent; public event SetStateActiveLinkEvent OnSetStateLinkEvent; public event SetStateActiveComponentEvent OnSetStateActiveComponentEvent; public event SetLinkColorEvent OnSetLinkColorEvent;<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412\u044b\u0448\u0435 \u0431\u044b\u043b \u043e\u043f\u0438\u0441\u0430\u043d \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b <strong>Draw<\/strong> \u0434\u043b\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438. \u041e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043d\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438, \u043a\u0430\u043a \u0438 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043a\u043b\u0430\u0441\u0441 <strong>LogicArea<\/strong> \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>IEditorDrawer<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public bool Draw(Rect container, bool lockInput) { PrepareGUIStyle();  logicAreaRect.width = container.width - 10f; logicAreaRect.height = container.height - _mainMenuHeightBar - _statusBarHeight - 20f;  if (VLECommon.Setting.ShowScrollBar) { logicScrollPosition = GUI.BeginScrollView(logicAreaRect, logicScrollPosition, logicRealRect, true, true); } else { logicScrollPosition = GUI.BeginScrollView(logicAreaRect, logicScrollPosition, logicRealRect, true, true, GUIStyle.none, GUIStyle.none); } { DrawAsDarkSkinImitation(() => GUI.BeginGroup(logicRealRect, GUI.skin.box), VLESetting.DarkGrayImitation); { VLEditorUtils.DrawGrid(logicRealRect, logicScrollPosition, gridColor, gridAccentColor);  LogicDraw(lockInput); HeaderDraw(); }   GUI.EndGroup(); } GUI.EndScrollView(false);  if (!lockInput) { HandleEvent(); }  return lockInput; }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u043e\u0441\u043e\u0431\u044b\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u0438 \u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043a\u0438\u043d\u0430 \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u043e \u043d\u0451\u043c \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 \u043f\u0440\u043e \u043c\u0430\u0445\u0438\u043d\u0430\u0446\u0438\u0438 ?<\/p>\n<p>\u0421 \u0446\u0435\u043b\u044c\u044e \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u043b\u043e\u0433\u0438\u043a\u0438, \u0432 \u043d\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0447\u0435\u0440\u0435\u0437 <strong>Draw&amp;Drop<\/strong> \u0444\u0430\u0439\u043b\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f. \u0420\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u044d\u0442\u043e \u0447\u0435\u0440\u0435\u0437 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c <strong>Unity3d<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void RepaintHandler(Event ev) {     var receivedData = DragAndDrop.GetGenericData(\"VLEDragData\");      if (receivedData != null)     {         if (receivedData is VLECatalog.CatalogComponent)         {             SetDragAndDropVisualMode(DragAndDropVisualMode.Link);              var catalogComponent = (VLECatalog.CatalogComponent)receivedData;             var boxStyle = new GUIStyle(GUI.skin.box);              boxStyle.normal.textColor = catalogComponent.ComponentColor;              GUI.Box(new Rect(ev.mousePosition.x, ev.mousePosition.y, 150f, 25f), catalogComponent.Name, boxStyle);         }         else if (receivedData is LinkingPointData)         {             SetDragAndDropVisualMode(DragAndDropVisualMode.Move);              var outputPoint = (LinkingPointData)receivedData;             var sourcePoint = outputPoint.Center + logicAreaRect.position - logicScrollPosition;              sourcePoint.x = Mathf.Clamp(sourcePoint.x, logicAreaRect.position.x, float.MaxValue);             sourcePoint.y = Mathf.Clamp(sourcePoint.y, logicAreaRect.position.y, float.MaxValue);              var targetIsInversion = false;             var color = Color.white;              for (var i = 0; i &lt; _logicWidgets.Count; i++)             {                 var component = _logicWidgets[i] as IComponentWidget;                  if (component != null)                 {                     var value = CheckAcceptedInputPoint(ev.mousePosition, component, outputPoint.DataType);                      if (value == -1)                     {                         DragAndDrop.visualMode = DragAndDropVisualMode.Rejected;                         targetIsInversion = component.IsInversion;                         color = Color.red;                         break;                     }                     else if (value == 1)                     {                         DragAndDrop.visualMode = DragAndDropVisualMode.Link;                         targetIsInversion = component.IsInversion;                         color = Color.green;                         break;                     }                 }             }              VLEditorUtils.DrawBezierLink(sourcePoint, ev.mousePosition, ((VLEComponent)outputPoint.Component).IsInversion, targetIsInversion, color);         }     }     else if (DragAndDrop.objectReferences.Length > 0)     {         var componentScript = DragAndDrop.objectReferences[0] as UnityEditor.MonoScript;          if (componentScript != null)         {             var componentType = componentScript.GetClass();              if (typeof(Core.LogicComponent).IsAssignableFrom(componentType))             {                 SetDragAndDropVisualMode(DragAndDropVisualMode.Link);                  var attributes = componentType.GetCustomAttributes(typeof(ComponentDefinitionAttribute), true);                  if (attributes.Length > 0)                 {                     var attributeData = (ComponentDefinitionAttribute)attributes[0];                      var color = (Color)VLECommon.Setting.ColorComponent;                      if (!ColorUtility.TryParseHtmlString(attributeData.Color, out color))                     {                         color = VLECommon.Setting.ColorComponent;                     }                      var boxStyle = new GUIStyle(GUI.skin.box);                      boxStyle.normal.textColor = color;                      GUI.Box(new Rect(ev.mousePosition.x, ev.mousePosition.y, 150f, 25f), attributeData.Name, boxStyle);                 }             }             else             {                 SetDragAndDropVisualMode(DragAndDropVisualMode.Rejected);             }         }         else         {             SetDragAndDropVisualMode(DragAndDropVisualMode.Rejected);         }     } }  private void DragPerformHandler(Event ev) {     DragAndDrop.AcceptDrag();      if (DragAndDrop.visualMode == DragAndDropVisualMode.Rejected) return;      var receivedData = DragAndDrop.GetGenericData(\"VLEDragData\");      if (receivedData != null)     {         if (receivedData is VLECatalog.CatalogComponent)         {             OnAddComponent((VLECatalog.CatalogComponent)receivedData, GetLogicAreaPosition(ev.mousePosition));         }         else if (receivedData is LinkingPointData)         {             var outputPoint = (LinkingPointData)receivedData;              for (var i = 0; i &lt; _logicWidgets.Count; i++)             {                 var component = _logicWidgets[i] as IComponentWidget;                  if (component != null)                 {                     var value = CheckAcceptedInputPoint(ev.mousePosition, component, outputPoint.DataType);                      if (value == 1)                     {                         var inputPoint = component.GetLinkAcceptedPoint();                          OnAddLink(outputPoint, inputPoint);                         break;                     }                 }             }         }          DragAndDrop.SetGenericData(\"VLEDragData\", null);     }     else if (DragAndDrop.objectReferences.Length > 0)     {         var componentScript = DragAndDrop.objectReferences[0] as UnityEditor.MonoScript;          if (componentScript != null)         {             var componentType = componentScript.GetClass();              if (typeof(Core.LogicComponent).IsAssignableFrom(componentType))             {                 var attributes = componentType.GetCustomAttributes(typeof(ComponentDefinitionAttribute), true);                  if (attributes.Length > 0)                 {                     var attributeData = (ComponentDefinitionAttribute)attributes[0];                      var color = (Color)VLECommon.Setting.ColorComponent;                      if (!ColorUtility.TryParseHtmlString(attributeData.Color, out color))                     {                         color = VLECommon.Setting.ColorComponent;                     }                      var catalogComponent = new VLECatalog.CatalogComponent(attributeData.Name, attributeData.Tooltip, componentType, color);                      OnAddComponent(catalogComponent, GetLogicAreaPosition(ev.mousePosition));                 }             }         }     }      ev.Use(); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0442\u0443\u0442 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0438\u043a\u0430\u043a\u043e\u0439 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0432 \u043d\u0451\u043c \u043d\u0435\u0442, \u043e\u0434\u043d\u0430\u043a\u043e \u0435\u0441\u0442\u044c \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/p>\n<ol>\n<li>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0443\u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u2014 \u044d\u0442\u043e \u0441\u043a\u0440\u0438\u043f\u0442, \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435 <strong>MonoBehaviour<\/strong> \u0442\u0438\u043f, \u0430 <strong>UnityEditor.MonoScript.<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 <strong>GenericData<\/strong> \u0434\u043b\u044f <strong>DragAndDrop<\/strong> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043c, \u0433\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <strong>Drag<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432 \u043b\u043e\u0433\u0438\u043a\u0443, \u043a\u043e\u0434 \u0442\u0430\u043a\u0436\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u0431\u043b\u043e\u043a\u0435:<\/p>\n<pre><code class=\"cs\">else if (receivedData is LinkingPointData)<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u043b\u044e\u0431\u043e\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 <strong>Unity<\/strong>, \u043d\u0443\u0436\u043d\u043e \u043e\u0442\u0441\u0435\u044f\u0442\u044c \u0442\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u043b\u043e\u0433\u0438\u043a\u0438, \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"cs\">var componentScript = DragAndDrop.objectReferences[0] as UnityEditor.MonoScript;  if (componentScript != null) {     var componentType = componentScript.GetClass();      if (typeof(Core.LogicComponent).IsAssignableFrom(componentType))     {         \/\/\/     } }<\/code><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u043a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u0435\u0434\u0438\u043d\u0438\u0447\u043d\u044b\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u043c, \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b \u0440\u0430\u0437\u0443\u043c\u043d\u043e\u0433\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f (\u043f\u043e\u0437\u0438\u0446\u0438\u0438) \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435 \u043f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u0445 \u0431\u043e\u043b\u0435\u0435, \u0447\u0435\u043c \u0434\u0432\u0430 \u0441\u0440\u0430\u0437\u0443. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043a\u043e\u0433\u0434\u0430-\u043d\u0438\u0431\u0443\u0434\u044c \u044f \u0440\u0435\u0448\u0443 \u044d\u0442\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443<\/em>?<em>.<\/em><\/p>\n<h4>\u0421\u0442\u0440\u043e\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430<\/h4>\n<p>\u0421\u0442\u0440\u043e\u043a\u0430 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u2014 \u044d\u0442\u043e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0441\u044f:<\/p>\n<ul>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0435\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0445 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u043b\u043e\u0433\u0438\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0430\u0439\u043c\u0435\u0440 \u0430\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u0432 \u0431\u0443\u0444\u0435\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0422\u0435\u043a\u0443\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0430.<\/p>\n<\/li>\n<\/ul>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (Status Bar)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLELogicEditor     {         private class StatusBar : IEditorDrawer, IDisposable         {             public delegate void SaveLogicEvent();             public event SaveLogicEvent OnSaveLogic;              private Rect _statusBarRect = new Rect(5f, 0f, 0f, 0f);             private Rect _positionRect = new Rect(2f, 2f, 200f, 0f);              private GUIStyle _positionStyle;             private GUIStyle _labelStyle;              private bool _guiStylePrepared;             private float _autoSaveTimer = float.NegativeInfinity;             private double _previousTime;              private readonly IList&lt;ILogicWidget> _currentVLEWidgets;              public StatusBar(IList&lt;ILogicWidget> currentVLEWidgets)             {                 _currentVLEWidgets = currentVLEWidgets;                 _statusBarRect.height = _statusBarHeight;                 _positionRect.height = _statusBarHeight - 4f;             }              public void Dispose()             {                 foreach (var eventHandler in OnSaveLogic.GetInvocationList())                 {                     OnSaveLogic -= (SaveLogicEvent)eventHandler;                 }             }              public bool Draw(Rect container, bool lockInput)             {                 UpdateGUIStyle();                  _statusBarRect.width = container.width - 10f;                 _statusBarRect.y = container.height - _statusBarRect.height - 5f;                 _positionRect.x = _statusBarRect.width - _positionRect.width - 5f;                  DrawAsDarkSkinImitation(() => GUILayout.BeginArea(_statusBarRect, GUI.skin.box), VLESetting.DarkGrayImitation);                 {                     GUILayout.BeginHorizontal();                     {                         if (VLECommon.Setting.MaximumComponents > 0)                         {                             GUILayout.Label($\"&lt;color=orange>Logic Components:&lt;\/color> &lt;color=white>{_currentVLEWidgets.Count} \/ {VLECommon.Setting.MaximumComponents}&lt;\/color>\",                                             _labelStyle,                                             GUILayout.ExpandHeight(true),                                             GUILayout.MaxWidth(175f));                         }                          if (VLECommon.UnsavedChanges > 0)                         {                             Separator();                             GUILayout.Label($\"&lt;color=orange>Unsaved changes:&lt;\/color> &lt;color=white>{VLECommon.UnsavedChanges}&lt;\/color>\",                                             _labelStyle,                                             GUILayout.ExpandHeight(true),                                             GUILayout.MaxWidth(150f));                              if (VLECommon.Setting.AutoSave)                             {                                 AutoSaveTimer();                                  Separator();                                 GUILayout.Label($\"&lt;color=orange>Save over:&lt;\/color> &lt;color=white>{GetTimeStr(_autoSaveTimer)}&lt;\/color>\",                                                 _labelStyle,                                                 GUILayout.ExpandHeight(true),                                                 GUILayout.MaxWidth(150f));                             }                         }                         else                         {                             _autoSaveTimer = float.NegativeInfinity;                         }                          if (VLECommon.BufferCounter > 0)                         {                             Separator();                             GUILayout.Label($\"&lt;color=orange>\u0421lipboard components:&lt;\/color> &lt;color=white>{VLECommon.BufferCounter}&lt;\/color>\",                                             _labelStyle,                                             GUILayout.ExpandHeight(true),                                             GUILayout.MaxWidth(150f));                         }                     }                     GUILayout.EndHorizontal();                      var scaleValue = VLECommon.CurrentEditorScale * 100f;                     var reverseScale = 1f \/ VLECommon.CurrentEditorScale;                      if (VLECommon.SelectedWidget != null)                     {                         var x = Mathf.Round(VLECommon.SelectedWidget.Area.position.x * reverseScale);                         var y = Mathf.Round(VLECommon.SelectedWidget.Area.position.y * reverseScale);                          GUI.Label(_positionRect, $\"[x: {x}; y: {y}] &lt;color=orange>[{scaleValue}%]&lt;\/color>\", _positionStyle);                     }                     else                     {                         GUI.Label(_positionRect, $\"&lt;color=orange>[{scaleValue}%]&lt;\/color>\", _positionStyle);                     }                 }                 GUILayout.EndArea();                  return lockInput;             }              private void UpdateGUIStyle()             {                 if (_guiStylePrepared) return;                  _positionStyle = new GUIStyle(GUI.skin.label);                 _positionStyle.alignment = TextAnchor.MiddleRight;                 _positionStyle.richText = true;                  if (!EditorGUIUtility.isProSkin)                 {                     _positionStyle.normal.textColor = Color.white;                 }                  _labelStyle = new GUIStyle(GUI.skin.label);                 _labelStyle.alignment = TextAnchor.MiddleLeft;                 _labelStyle.richText = true;                  _guiStylePrepared = true;             }              private void Separator() => GUILayout.Box(string.Empty, GUILayout.Width(4f), GUILayout.ExpandHeight(true));                         private string GetTimeStr(float seconds)             {                 var timeSpan = TimeSpan.FromSeconds(seconds);                 var timeStr = ((timeSpan.Minutes &lt; 10) ? $\"0\" + timeSpan.Minutes.ToString() : timeSpan.Minutes.ToString()) + \":\" +                                ((timeSpan.Seconds &lt; 10) ? \"0\" + timeSpan.Seconds.ToString() : timeSpan.Seconds.ToString());                  return timeStr;             }              private void AutoSaveTimer()             {                 if (_autoSaveTimer == float.NegativeInfinity)                 {                     _autoSaveTimer = VLECommon.Setting.AutoSavePeriod;                     _previousTime = EditorApplication.timeSinceStartup;                 }                  _autoSaveTimer = Mathf.Clamp(_autoSaveTimer - (float)(EditorApplication.timeSinceStartup - _previousTime), 0f, float.MaxValue);                  if (_autoSaveTimer == 0f)                 {                     _autoSaveTimer = float.NegativeInfinity;                     _previousTime = 0f;                      OnSaveLogic();                 }                  _previousTime = EditorApplication.timeSinceStartup;             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u0420\u0438\u0441\u0443\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u043e\u0433\u0440\u0443\u0437\u0438\u0442\u0441\u044f \u0432 \u0434\u0435\u0431\u0440\u0438 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430 \u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445 \u0432 <strong>uViLEd<\/strong>, \u0445\u043e\u0447\u0443 \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u043d\u0443\u0442\u044c \u0438 \u0430\u043a\u0446\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0435\u0439 \u043d\u0430 \u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0438 \u043e\u0431\u044a\u0435\u043c\u043d\u044b\u043c \u0432\u043e \u0432\u0441\u0435\u0439 \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u0431\u0443\u0434\u0443 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u0438 \u043d\u0435 \u0431\u0443\u0434\u0443 \u0433\u043b\u0443\u0431\u043e\u043a\u043e \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u0438\u043a\u0443 \u043a\u043e\u0434\u0430, \u0435\u0441\u043b\u0438 \u0442\u043e\u0433\u043e \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f. <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043e\u0431\u0449\u0443\u044e \u0431\u043b\u043e\u043a-\u0441\u0445\u0435\u043c\u0443 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"584\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ade\/f38\/9fa\/adef389faf8eb0fa11205fea0c76c0a6.png\" data-width=\"1639\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0418\u0442\u0430\u043a, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0438\u0435 \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 (\u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a, \u0442\u0435\u043b\u043e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u0442.\u043f.). \u0421\u0430\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u043c <strong>ILogicWidget<\/strong> \u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0435\u0439 <strong>VLEWidget<\/strong>. \u0412\u0441\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f\u043c\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 <strong>IChildWidget<\/strong> \u0438 <strong>IWidgetContainer<\/strong>. \u0412\u0442\u043e\u0440\u0430\u044f \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0441\u0443\u0442\u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u043c \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0435\u0435 \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043e\u0431\u0443\u0441\u043b\u043e\u0432\u043b\u0435\u043d\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u044c\u044e \u043e\u043f\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u044b\u043c \u0446\u0435\u043b\u044b\u043c. <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0432\u0441\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0435 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<h3>\u041e\u0441\u043d\u043e\u0432\u0430<\/h3>\n<p>\u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435 \u0432 \u043e\u0441\u043d\u043e\u0432\u0435 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u0435\u0436\u0438\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>ILogicWidget<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public interface ILogicWidget     {         string Id { get; }         string Name { get; set; }         string Comment { get; set; }         string Description { get; }         string Group { get; set; }         ScriptableObject Instance { get; }         Type InstanceType { get; }         Core.LogicStorage.ComponentsStorage.ComponentData ComponentStorage { get; }         Color WidgetColor { get; set; }         Rect Area { get; }         bool IsSelected { get; }          void Draw(bool lockMouse);         void SetPosition(Vector2 newPosition);         void Select(bool state, bool isMultiSelect = true);     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043f\u043e\u043b\u044f:<\/p>\n<ul>\n<li>\n<p><strong>Instance<\/strong> \u2013 \u044d\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong>Type<\/strong> \u2013 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0442\u0438\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p><strong>ComponentStorage<\/strong> \u2013 \u044d\u0442\u043e \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 ScriptableObject \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0435\u0439 <strong>VLEWidget<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public abstract partial class VLEWidget : ILogicWidget, IDisposable {     public string Name     {         get => _name;         set => VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, _name = value);     }      public string Comment     {         get => _comment;         set => VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, _comment = value, false);     }      public string Group     {         get => _group;         set => VLECommon.CurrentLogic.Components.ModiftyComponentGroup(Id, _group = value);     }      public Color WidgetColor     {         get => _widgetColor;         set => VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, _widgetColor = value);     }      public ScriptableObject Instance     {         get         {             if (!EditorApplication.isPlaying)             {                 if (_instance == null)                 {                     _instance = ScriptableObject.CreateInstance(InstanceType);                     JsonUtility.FromJsonOverwrite(ComponentStorage.JsonData, _instance);                 }                  return _instance;             }             else             {                 if (VLECommon.CurrentLogicController.RuntimeComponentInstances != null &amp;&amp;                     VLECommon.CurrentLogicController.RuntimeComponentInstances.ContainsKey(Id))                 {                     return VLECommon.CurrentLogicController.RuntimeComponentInstances[Id];                 }                 else                 {                     return _instance;                 }             }         }     }      public string Id { get; }     public Type InstanceType { get; }     public string Description { get; }     public Core.LogicStorage.ComponentsStorage.ComponentData ComponentStorage { get; }     public bool IsSelected { get; private set; } = false;      protected readonly IDictionary&lt;Type, Type> widgetTypeDict = new Dictionary&lt;Type, Type>();      private string _name;     private string _comment;     private string _group;      private Color _widgetColor;      private ScriptableObject _instance;      public VLEWidget(Core.LogicStorage.ComponentsStorage.ComponentData componentStorageData)     {         ComponentStorage = componentStorageData;         Id = ComponentStorage.Id;         _group = componentStorageData.Group;          InstanceType = AssemblyHelper.GetAssemblyType(ComponentStorage.Assembly, ComponentStorage.Type);         _instance = ScriptableObject.CreateInstance(InstanceType);          JsonUtility.FromJsonOverwrite(ComponentStorage.JsonData, _instance);          var attrubutes = InstanceType.GetCustomAttributes(typeof(ComponentDefinitionAttribute), true);          if (attrubutes.Length > 0)         {             var componentDefinition = (ComponentDefinitionAttribute)attrubutes[0];              if (ComponentStorage.InstanceName.Length > 0)             {                 _name = ComponentStorage.InstanceName;             }             else             {                 Name = componentDefinition.Name;             }              if (!ColorUtility.TryParseHtmlString(componentDefinition.Color, out _widgetColor))             {                 _widgetColor = VLECommon.Setting.ColorComponent;             }              if (ComponentStorage.Color.Length > 0)             {                 Color inctanceColor;                  if (ColorUtility.TryParseHtmlString(ComponentStorage.Color, out inctanceColor))                 {                     _widgetColor = inctanceColor;                 }             }              Description = componentDefinition.Tooltip;         }         else         {             if ((ComponentStorage.InstanceName.Length > 0))             {                 _name = ComponentStorage.InstanceName;             }             else             {                 Name = InstanceType.Name;             }              _widgetColor = VLECommon.Setting.ColorComponent;              if (ComponentStorage.Color.Length > 0)             {                 Color inctanceColor;                  if (ColorUtility.TryParseHtmlString(ComponentStorage.Color, out inctanceColor))                 {                     _widgetColor = inctanceColor;                 }             }              Description = InstanceType.Name;         }          _comment = ComponentStorage.Comment;          PrepareChildWidget();     }      protected virtual void PrepareChildWidget()     {         mainWidget = CreateWidget&lt;MainWidget>((Vector2)ComponentStorage.Position);          mainWidget.AddWidget(bodyWidget = CreateWidget&lt;BodyWidget>(this, mainWidget));         mainWidget.AddWidget(headerWidget = CreateWidget&lt;HeaderWidget>(this));         mainWidget.AddWidget(descriptionWidget = CreateWidget&lt;DescriptionWidget>(this));     }      protected void ReplaceWidget&lt;Source, Target>()     {         var sourceType = typeof(Source);         var targetType = typeof(Target);          if (widgetTypeDict.ContainsKey(sourceType))         {             widgetTypeDict[sourceType] = targetType;         }         else         {             widgetTypeDict.Add(sourceType, targetType);         }     }      protected T CreateWidget&lt;T>(params object[] args)     {         var sourceType = typeof(T);         var targetType = sourceType;          if (widgetTypeDict.ContainsKey(sourceType))         {             targetType = widgetTypeDict[sourceType];         }          return (T)Activator.CreateInstance(targetType, args);     }      public void Select(bool state, bool isMultiSelect = true)     {         IsSelected = state;          if (isMultiSelect)         {             if (IsSelected)             {                 if (!VLECommon.SelectedWidgets.Contains(this))                 {                     VLECommon.SelectedWidgets.Add(this);                 }             }             else             {                 if (VLECommon.SelectedWidgets.Contains(this))                 {                     VLECommon.SelectedWidgets.Remove(this);                 }             }         }         else         {             if (IsSelected)             {                 if (VLECommon.SelectedWidget != this)                 {                     if (VLECommon.SelectedWidget != null)                     {                         VLECommon.SelectedWidget.Select(false, false);                     }                      VLECommon.SelectedWidget = this;                 }             }             else             {                 if (VLECommon.SelectedWidget == this)                 {                     VLECommon.SelectedWidget = null;                 }             }         }     }      public virtual void Dispose() { } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u0434\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438 \u0437\u0430\u043c\u0435\u043d\u044b \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 <strong>CreateWidget<\/strong> \u0438 <strong>ReplaceWidget<\/strong>. \u041f\u043e \u0441\u0443\u0442\u0438, \u044d\u0442\u043e \u043d\u0435\u043a\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0430\u0431\u0440\u0438\u043a\u0438. \u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u043d\u0438\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c, \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043b\u0438\u0431\u043e \u043f\u043e \u0442\u0430\u0439\u043c\u0435\u0440\u0443 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d.<\/em><\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043a\u043b\u0430\u0441\u0441 <strong>VLEComponent<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLEComponent : VLEWidget, IComponentWidget, IParameterContainer     {         public class ParameterValueData         {             public string Name;             public object Value;         }          public bool IsActive { get; private set; } = true;         public bool IsInversion => _usedInternalInversionValue ? _inversionInputOutputPoints : VLECommon.Setting.InverstionIOPoint;         public bool IsContainsParameters => parametersContainer != null;         public bool IsMinimized { get; private set; } = false;         public bool IsHideParameter { get; private set; } = false;         public bool IsCanMinimize { get; private set; } = false;         public bool TracertState { get; private set; } = false;         public bool TracertInProgress { get; private set; } = false;          private bool _inversionInputOutputPoints;         private bool _usedInternalInversionValue;          public VLEComponent(LogicStorage.ComponentsStorage.ComponentData componentStorageData) : base(componentStorageData)         {             IsActive = ComponentStorage.IsActive;             IsMinimized = ComponentStorage.CollapseIOPoints;             IsHideParameter = ComponentStorage.CollapseParameter;             _inversionInputOutputPoints = ComponentStorage.InversionPoint;             _usedInternalInversionValue = ComponentStorage.InternalInversionState;              bodyWidget.AddWidget(CreateWidget&lt;MenuWidget>(this));             bodyWidget.AddWidget(CreateWidget&lt;StateWidget>(this));              PrepareInputOutputWidgets();             PrepareParameterWidgets();         }          public void MakeTracert(bool state, bool inProgress)         {             TracertState = state;             TracertInProgress = inProgress;         }          public void SetActiveComponent(bool state)         {             IsActive = state;              VLECommon.CurrentLogic.Components.ModifyComponentActive(Id, IsActive);             VLECommon.ComponentChangedActive(this);         }          public void SetCollapseComponent(bool state)         {             if ((!IsCanMinimize &amp;&amp; IsMinimized == true &amp;&amp; state == false) ||                 (IsCanMinimize &amp;&amp; (IsMinimized != state)))             {                 IsMinimized = state;                  if (IsMinimized)                 {                     bodyWidget.RemoveWidget(pointsContainer);                     bodyWidget.RemoveWidget(parametersContainer);                     bodyWidget.AddWidget(pointsCollapsedContainer);                 }                 else                 {                     bodyWidget.RemoveWidget(pointsCollapsedContainer);                     bodyWidget.AddWidget(pointsContainer);                      if (parametersContainer != null)                     {                         bodyWidget.AddWidget(parametersContainer);                     }                 }                  VLECommon.UnsavedChanges++;                 VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, IsMinimized, true);             }         }          public void SetCollapseParameter(bool state)         {             if (parametersContainer == null || IsHideParameter == state) return;              IsHideParameter = state;              if (IsHideParameter)             {                 parametersContainer.RemoveWidget(parameterValuesContainter);             }             else             {                 parametersContainer.AddWidget(parameterValuesContainter);             }              VLECommon.UnsavedChanges++;             VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, IsHideParameter, false);         }          public void SetInversionPoints(bool state)         {             _usedInternalInversionValue = true;             _inversionInputOutputPoints = state;              VLECommon.UnsavedChanges++;             VLECommon.CurrentLogic.Components.ModiftyComponentByLogic(Id, _inversionInputOutputPoints);         }          protected override void HeaderDoubleClick()         {             if (!IsCanMinimize) return;                          SetCollapseComponent(!IsMinimized);                     }          protected override void MouseDrag(Event ev)         {             if (!isMoved &amp;&amp; !eventHandleForbidden)             {                 if (Area.Contains(ev.mousePosition))                 {                     var draggedPoint = GetDraggedOutputPoint(ev.mousePosition);                      if (draggedPoint != null)                     {                         DragAndDrop.PrepareStartDrag();                         DragAndDrop.objectReferences = new UnityEngine.Object[0];                         DragAndDrop.paths = new string[0];                         DragAndDrop.SetGenericData(\"VLEDragData\", draggedPoint);                         DragAndDrop.StartDrag(\"VLEDragData\");                          ev.Use();                     }                 }             }              base.MouseDrag(ev);         }          public override void Draw(bool lockInput)         {             if (!lockInput)             {                 HandleEvent(Event.current);             }              var color = GUI.color;              if (!IsActive)             {                 GUI.color = Color.gray;             }              mainWidget.Draw();              GUI.color = color;         }          public override void Dispose()         {             var fields = InstanceType.GetFields(BindingFlags.Public | BindingFlags.Instance);              foreach (var fieldInfo in fields)             {                 if (fieldInfo.FieldType == typeof(VLObject))                 {                     var VLEObject = (VLObject)fieldInfo.GetValue(Instance);                      VLECommon.CurrentLogicController.SetObject(VLEObject.Id, null);                 }                 else if (fieldInfo.FieldType == typeof(VLObject[]))                 {                     var vsObjects = (VLObject[])fieldInfo.GetValue(Instance);                      foreach (var VLEObject in vsObjects)                     {                         VLECommon.CurrentLogicController.SetObject(VLEObject.Id, null);                     }                 }                 else if (fieldInfo.FieldType == typeof(List&lt;VLObject>))                 {                     var vsObjects = (List&lt;VLObject>)fieldInfo.GetValue(Instance);                      foreach (var VLEObject in vsObjects)                     {                         VLECommon.CurrentLogicController.SetObject(VLEObject.Id, null);                     }                 }             }         }     } }<\/code><\/pre>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0443\u043b\u0435\u0432\u044b\u0445 \u0441\u0432\u043e\u0439\u0441\u0442\u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c <strong>false<\/strong>, \u044d\u0442\u043e \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438 \u0438 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u0432\u0434\u0440\u0443\u0433 \u043a\u0442\u043e \u043d\u0435 \u0437\u043d\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <strong>bool<\/strong> \u044d\u0442\u043e <strong>false<\/strong>, \u043a\u0430\u043a <strong>0f<\/strong> \u0443 <strong>float<\/strong>.<\/p>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u043f\u043e\u043c\u0438\u043c\u043e \u0431\u0430\u0437\u043e\u0432\u043e\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 <strong>VLEWidget<\/strong>, \u043a\u043b\u0430\u0441\u0441 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0435\u0449\u0435 \u0434\u0432\u0430 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <strong>IComponentWidget<\/strong> \u0438 <strong>IParamatersContainer<\/strong>. \u041f\u0435\u0440\u0432\u044b\u0439 \u0441\u043b\u0443\u0436\u0438\u0442 \u0434\u043b\u044f \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u0438\u043a\u0438 \u043f\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443 (\u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0435\u0441\u0442\u044c \u0435\u0449\u0435 \u0441\u0432\u044f\u0437\u0438, \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u0433\u0440\u0443\u043f\u043f\u044b), \u0432\u0442\u043e\u0440\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c \u0432 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0438 \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u0435 (\u0437\u0430\u043f\u0443\u0441\u043a \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435) \u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438. \u0422\u0430\u043a\u0436\u0435 \u0441\u0442\u043e\u0438\u0442 \u043f\u043e\u044f\u0441\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>Dispose<\/strong>: \u0435\u0441\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u043b\u043e\u0433\u0438\u043a\u0438, \u0430 \u0432 \u043d\u0435\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043b\u0438\u0441\u044c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u043a\u043b\u0430\u0441\u0441\u0430 <strong>VLObject<\/strong> (\u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b <strong>Unity<\/strong>), \u0442\u043e \u0438\u0445 \u043d\u0430\u0434\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0438 \u0434\u0435\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0445\u043e\u043b\u0434\u0435\u0440\u044b, \u0434\u0430\u0431\u044b \u043d\u0435 \u043d\u0430\u043f\u043b\u043e\u0434\u0438\u043b\u043e\u0441\u044c \u043b\u0438\u0448\u043d\u0435\u0433\u043e.<\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IComponentWidget<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public interface IComponentWidget     {         bool IsActive { get; }         bool IsMinimized { get; }         bool IsHideParameter { get; }         bool IsInversion { get; }         bool IsCanMinimize { get; }         bool IsContainsParameters { get; }          Rect GetInputPointRect(string pointName);         Rect GetOutputPointRect(string pointName);          int InputPointCanBeAccepted(Vector2 position, Type type);         LinkingPointData GetLinkAcceptedPoint();          void SetActiveComponent(bool state);         void SetCollapseComponent(bool state);         void SetCollapseParameter(bool state);         void SetInversionPoints(bool state);          bool TracertState { get; }         bool TracertInProgress { get; }          void MakeTracert(bool state, bool inProgress);     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u0445\u043e\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043d\u0430 \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<ul>\n<li>\n<p><strong>InputPointCanBeAccepted<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u0438 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<\/li>\n<li>\n<p><strong>GetLinkAcceptedPoint<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0432 \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0436\u0435\u043b\u0430\u0435\u0442 \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0441\u043e \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0432\u0430 \u043f\u043e\u043b\u044f (<\/em><strong><em>TracertState<\/em><\/strong><em>, <\/em><strong><em>TracertInProgress<\/em><\/strong><em>) \u0438 \u043c\u0435\u0442\u043e\u0434 <\/em><strong><em>MakeTracert<\/em><\/strong><em> \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u0440\u0435\u0436\u0438\u043c\u0443 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043b\u043e\u0433\u0438\u043a\u0438. \u042d\u0442\u043e\u0442 \u0430\u0441\u043f\u0435\u043a\u0442 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u0443\u043d\u043a\u0442\u0435.<\/em><\/p>\n<details class=\"spoiler\">\n<summary>\u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 IParameterContainer<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public interface IParameterContainer     {         void UpdateParameterValues();     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u043c\u044b\u0445 \u0432 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<h3>\u0412\u0438\u0434\u0436\u0435\u0442\u044b<\/h3>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0435 \u0437\u0430 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u0430\u0441\u043f\u0435\u043a\u0442\u043e\u0432 \u0438\u0445 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0438\u0434\u0430, \u044d\u0442\u0438\u043c\u0438 \u0432\u0438\u0434\u0436\u0435\u0442\u0430\u043c\u0438 \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b, \u0442\u0430\u043a \u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u044e\u0442:<\/p>\n<ul>\n<li>\n<p><strong>MainWidget<\/strong> \u2013 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>BodyWidget<\/strong> \u2013 \u043a\u043e\u043d\u0442\u0435\u043d\u0435\u0439\u0440 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0442\u0435\u043b\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>PointsContainer<\/strong> \u2013 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a.<\/p>\n<\/li>\n<li>\n<p><strong>ParametersContainer<\/strong> \u2013 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>ParameterValuesContainer<\/strong> \u2013 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: \u043a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0434\u043b\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u0434\u0432\u0430 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430, \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0432\u0443\u0445 \u0440\u0435\u0436\u0438\u043c\u043e\u0432 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f, \u043c\u0438\u043d\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0441\u043e\u043a\u0440\u044b\u0442\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0432\u0438\u0434\u0436\u0435\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><strong>HeaderWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>DescriptionWidget<\/strong>\u00a0 &#8212; \u0432\u0438\u0434\u0436\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>MenuWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u0433\u043e \u043c\u0435\u043d\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>StateWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>PointWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0438\u043b\u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ParameterValueWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>VariableLinkWidget<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u043d\u0435 \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a\u043e\u0434 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u0430, \u0432 \u0446\u0435\u043b\u043e\u043c \u043e\u043d\u0438 \u0441\u0442\u0440\u043e\u044f\u0442\u0441\u044f \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0448\u0430\u0431\u043b\u043e\u043d\u0443. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043a\u043e\u0434 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a \u0438 \u0441\u0430\u043c \u0432\u0438\u0434\u0436\u0435\u0442 \u0442\u043e\u0447\u043a\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public abstract partial class VLEWidget     {         public abstract class WidgetComponentsContainer : IChildWidget, IWidgetContainer         {             public virtual Rect Area => widgetVirtualRect.GetRect(VLECommon.CurrentEditorScale);             public virtual Vector2 Position             {                 get => widgetVirtualRect.GetRect(VLECommon.CurrentEditorScale).position;                 set => widgetVirtualRect.SetPosition(value, VLECommon.CurrentEditorScale);             }              public virtual Vector2 WorldPosition             {                 get => _worldPosition.GetPosition(VLECommon.CurrentEditorScale);                 set                 {                     var delta = value - WorldPosition;                      _worldPosition.SetPosition(value, VLECommon.CurrentEditorScale);                      UpdateChildWidgetWorldPosition(delta);                 }             }              protected VLEExtension.VLEVirtualRect widgetVirtualRect;              protected readonly List&lt;IChildWidget> widgets = new List&lt;IChildWidget>();             protected readonly IWidgetContainer rootContainer;              private VLEExtension.VLEVirtualPosition _worldPosition = new VLEExtension.VLEVirtualPosition(0f, 0f);              public WidgetComponentsContainer(IWidgetContainer root) => rootContainer = root;                         public virtual void RegisterStyle() { }             public virtual void Draw()             {                 for (var i = 0; i &lt; widgets.Count; i++)                 {                     var widget = widgets[i];                     widget.RegisterStyle();                     widget.Draw();                 }             }              public virtual void AddWidget(IChildWidget widget)             {                 widget.WorldPosition = widget.Position + WorldPosition;                  widgets.Add(widget);                  ResizeWidgetContainer();             }              public virtual void RemoveWidget(IChildWidget widget)             {                 if (widgets.Contains(widget))                 {                     widgets.Remove(widget);                      ResizeWidgetContainer();                 }             }              public virtual void ClearWidget() => widgets.Clear();                         public virtual void ResizeWidgetContainer()             {                 var yMax = 0f;                  foreach (var widget in widgets)                 {                     if (widget.Area.yMax > yMax)                     {                         yMax = widget.Area.yMax;                     }                 }                  widgetVirtualRect.SetHeight(yMax, VLECommon.CurrentEditorScale);                  UpdateRootContainer();             }              protected void UpdateRootContainer() => rootContainer?.ResizeWidgetContainer();             protected void UpdateChildWidgetWorldPosition(Vector2 delta) => widgets.SafeForEach(widget => widget.WorldPosition += delta);                     }          public abstract class ChildWidget : IChildWidget         {             public virtual Rect Area => widgetVirtualRect.GetRect(VLECommon.CurrentEditorScale);             public virtual Vector2 Position             {                 get => widgetVirtualRect.GetRect(VLECommon.CurrentEditorScale).position;                 set => widgetVirtualRect.SetPosition(value, VLECommon.CurrentEditorScale);             }              public virtual Vector2 WorldPosition             {                 get => _worldVirtualPosition.GetPosition(VLECommon.CurrentEditorScale);                 set => _worldVirtualPosition.SetPosition(value, VLECommon.CurrentEditorScale);             }              protected VLEExtension.VLEVirtualRect widgetVirtualRect;              private readonly VLEExtension.VLEVirtualPosition _worldVirtualPosition = new VLEExtension.VLEVirtualPosition(0f, 0f);              public virtual void RegisterStyle() { }             public abstract void Draw();         }     } }  <\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>\u041e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u0432\u0438\u0434\u0436\u0435\u0442\u044b)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLEComponent     {         public class PointsContainer : WidgetComponentsContainer         {             public PointsContainer(IWidgetContainer rootContinaer) : base(rootContinaer)             {                 widgetVirtualRect = new VLEExtension.VLEVirtualRect(0f, 50f, 250f, 0f);             }              public override void Draw()             {                 GUI.BeginGroup(Area);                 {                     base.Draw();                 }                 GUI.EndGroup();             }              public Rect GetPointRect(string pointName, PointTypeEnum pointType)             {                 var point = widgets.Find((widget) =>                 {                     var pointWidget = widget as PointWidget;                      return pointWidget.Point.PointType == pointType &amp;&amp; pointWidget.Point.Name == pointName;                 });                  if (point != null)                 {                     var worldRect = point.Area;                      worldRect.position = point.Area.position + WorldPosition;                      return worldRect;                 }                 else                 {                     return Rect.zero;                 }             }              public IChildWidget GetPointContainsPosition(Vector2 position, PointTypeEnum pointType)             {                 return widgets.Find((widget) =>                 {                     var pointWidget = (PointWidget)widget;                     var worldRect = widget.Area;                      worldRect.position = pointWidget.Area.position + WorldPosition;                      return pointWidget.Point.PointType == pointType &amp;&amp; worldRect.Contains(position);                 });             }              public override void ResizeWidgetContainer()             {                 var yMax = 0f;                  foreach (var widget in widgets)                 {                     if (widget.Area.yMax > yMax)                     {                         yMax = widget.Area.yMax;                     }                 }                  widgetVirtualRect.SetHeight(yMax + 10f * VLECommon.CurrentEditorScale, VLECommon.CurrentEditorScale);                  UpdateRootContainer();             }         }          public class PointWidget : ChildWidget         {             public InputOutputPointData Point { get; }              protected Rect inputConnectorRect => inputConnectorVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect outputConnectorRect => outputConnectorVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect inputConnectorVisualRect => inputConnectorDirectionVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect outputConnectorVisualRect => outputConnectorDirectionVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect inputPointNameRect => inputPointNameVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect outputPointNameRect => outputPointNameVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect inputConnectorPointRect => inputConnectorPointVirtualRect.GetRect(VLECommon.CurrentEditorScale);             protected Rect outputConnectorPointRect => outputConnectorPointVirtualRect.GetRect(VLECommon.CurrentEditorScale);              protected GUIStyle pointNameStyle;             protected GUIStyle connectorDirectionStyle;             protected GUIStyle connectorPointStyle;              protected VLEExtension.VLEVirtualRect inputConnectorVirtualRect = new VLEExtension.VLEVirtualRect(5f, 0f, 20f, 20f);             protected VLEExtension.VLEVirtualRect outputConnectorVirtualRect = new VLEExtension.VLEVirtualRect(228f, 0f, 20f, 20f);              protected VLEExtension.VLEVirtualRect inputConnectorDirectionVirtualRect = new VLEExtension.VLEVirtualRect(6f, 0f, 20f, 20f);             protected VLEExtension.VLEVirtualRect outputConnectorDirectionVirtualRect = new VLEExtension.VLEVirtualRect(225f, 0f, 20f, 20f);              protected VLEExtension.VLEVirtualRect inputConnectorPointVirtualRect = new VLEExtension.VLEVirtualRect(0f, 0f, 12f, 20f);             protected VLEExtension.VLEVirtualRect outputConnectorPointVirtualRect = new VLEExtension.VLEVirtualRect(237f, 0f, 12f, 20f);              protected VLEExtension.VLEVirtualRect inputPointNameVirtualRect = new VLEExtension.VLEVirtualRect(20f, 0f, 100f, 20f);             protected VLEExtension.VLEVirtualRect outputPointNameVirtualRect = new VLEExtension.VLEVirtualRect(130f, 0f, 100f, 20f);              protected VLEExtension.VLEVirualFontSize virtualFontSize = new VLEExtension.VLEVirualFontSize(11);              protected VLEExtension.VLEVirtualRect inputConnectorForExternalVirtualRect = new VLEExtension.VLEVirtualRect(2f, 0f, 10f, 20f);             protected VLEExtension.VLEVirtualRect outputConnectorForExternalVirtualRect = new VLEExtension.VLEVirtualRect(235f, 0f, 10f, 20f);              protected GUIContent pointContent;             protected GUIContent connectorDirectionContent;             protected GUIContent inversionConnectorDirectionContent;             protected GUIContent connectorPointContent;              protected Color connectorPointColor = new Color(0.75f, 0.75f, 0.75f, 1f);              protected Action currentDraw;              protected readonly IComponentWidget component;              public PointWidget(IComponentWidget baseComponent, InputOutputPointData pointData, int indexNumber)             {                 component = baseComponent;                 Point = pointData;                  connectorDirectionContent = EditorGUIUtility.IconContent(\"profiler.nextframe\");                 inversionConnectorDirectionContent = EditorGUIUtility.IconContent(\"profiler.prevframe\");                 connectorPointContent = new GUIContent(EditorGUIUtility.IconContent(\"blendsampler\"));                 connectorPointContent.tooltip = (Point.DataType != null) ? Point.DataType.Name : string.Empty;                  var yPosByIndexNumber = inputConnectorRect.y + (inputConnectorRect.height + Mathf.Round(5f * VLECommon.CurrentEditorScale)) * indexNumber;                  inputConnectorVirtualRect.SetY(yPosByIndexNumber, VLECommon.CurrentEditorScale);                 inputPointNameVirtualRect.SetY(yPosByIndexNumber, VLECommon.CurrentEditorScale);                 outputConnectorVirtualRect.SetY(yPosByIndexNumber, VLECommon.CurrentEditorScale);                 outputPointNameVirtualRect.SetY(yPosByIndexNumber, VLECommon.CurrentEditorScale);                  inputConnectorDirectionVirtualRect.SetY(inputConnectorRect.y + inputConnectorRect.height \/ 2f - inputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                  outputConnectorDirectionVirtualRect.SetY(outputConnectorRect.y + outputConnectorRect.height \/ 2f - outputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                  inputConnectorPointVirtualRect.SetY(inputConnectorRect.y + inputConnectorRect.height \/ 2f - inputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                  outputConnectorPointVirtualRect.SetY(outputConnectorRect.y + outputConnectorRect.height \/ 2f - outputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                  inputConnectorForExternalVirtualRect.SetY(inputConnectorRect.y + inputConnectorRect.height \/ 2f - inputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                  outputConnectorForExternalVirtualRect.SetY(outputConnectorRect.y + outputConnectorRect.height \/ 2f - outputConnectorVisualRect.height \/ 2f - 1f,                                                      VLECommon.CurrentEditorScale);                   switch (pointData.PointType)                 {                     case PointTypeEnum.Input:                         widgetVirtualRect = inputConnectorForExternalVirtualRect;                         currentDraw = DrawAsInputPoint;                         break;                     case PointTypeEnum.Output:                         widgetVirtualRect = outputConnectorForExternalVirtualRect;                         currentDraw = DrawAsOutputPoint;                         break;                 }             }              public override void RegisterStyle()             {                 if (pointNameStyle == null)                 {                     pointNameStyle = new GUIStyle(EditorGUIUtility.isProSkin ? GUI.skin.box : GUI.skin.label);                     pointNameStyle.clipping = TextClipping.Clip;                     pointNameStyle.fontSize = virtualFontSize.GetFontSize(VLECommon.CurrentEditorScale);                      connectorDirectionStyle = new GUIStyle(GUI.skin.label);                     connectorDirectionStyle.alignment = TextAnchor.MiddleLeft;                      connectorPointStyle = new GUIStyle(GUI.skin.label);                     connectorPointStyle.alignment = TextAnchor.MiddleLeft;                 }             }              public override void Draw()             {                 pointNameStyle.fontSize = virtualFontSize.GetFontSize(VLECommon.CurrentEditorScale);                 connectorDirectionStyle.fontSize = virtualFontSize.GetFontSize(VLECommon.CurrentEditorScale);                  currentDraw();             }              protected virtual void DrawConnector(Rect rectDirection, Rect rectPoint, Color color, GUIContent content)             {                 var guiColor = GUI.color;                  GUI.color = color;                  GUI.Label(rectDirection, content, connectorDirectionStyle);                 GUI.color = connectorPointColor;                  GUI.Label(rectPoint, connectorPointContent, connectorPointStyle);                 GUI.color = guiColor;             }              protected virtual void DrawInputPointName(Rect rect)             {                 pointNameStyle.normal.textColor = VLECommon.Setting.ColorInputPoint;                  if (!EditorGUIUtility.isProSkin)                 {                     pointNameStyle.alignment = component.IsInversion ? TextAnchor.MiddleRight : TextAnchor.MiddleLeft;                      VLELogicEditor.DrawAsDarkSkinImitation(() => GUI.Box(rect, string.Empty), VLESetting.DarkLightGrayImitation);                 }                 else                 {                     pointNameStyle.alignment = component.IsInversion ? TextAnchor.UpperRight : TextAnchor.UpperLeft;                 }                  VLEditorUtils.DrawLabelWithAutoTooltip(rect, Point.Name, Point.Tooltip, pointNameStyle);             }              protected virtual void DrawOutputPointName(Rect rect)             {                 pointNameStyle.normal.textColor = VLECommon.Setting.ColorOutputPoint;                  if (!EditorGUIUtility.isProSkin)                 {                     pointNameStyle.alignment = component.IsInversion ? TextAnchor.MiddleLeft : TextAnchor.MiddleRight;                      VLELogicEditor.DrawAsDarkSkinImitation(() => GUI.Box(rect, string.Empty), VLESetting.DarkLightGrayImitation);                 }                 else                 {                     pointNameStyle.alignment = component.IsInversion ? TextAnchor.UpperLeft : TextAnchor.UpperRight;                 }                  VLEditorUtils.DrawLabelWithAutoTooltip(rect, Point.Name, Point.Tooltip, pointNameStyle);             }              protected virtual void DrawAsInputPoint()             {                 var inputNameRect = component.IsInversion ? outputPointNameRect : inputPointNameRect;                                 var connectorVisualRect = component.IsInversion ? outputConnectorVisualRect : inputConnectorVisualRect;                 var connectorContent = component.IsInversion ? inversionConnectorDirectionContent : connectorDirectionContent;                 var connectorPointRect = component.IsInversion ? outputConnectorPointRect : inputConnectorPointRect;                  widgetVirtualRect = component.IsInversion ? outputConnectorForExternalVirtualRect : inputConnectorForExternalVirtualRect;                  DrawConnector(connectorVisualRect, connectorPointRect, VLECommon.Setting.ColorInputPoint, connectorContent);                 DrawInputPointName(inputNameRect);             }              protected virtual void DrawAsOutputPoint()             {                 var outputNameRect = component.IsInversion ? inputPointNameRect : outputPointNameRect;                                var connectorVisualRect = component.IsInversion ? inputConnectorVisualRect : outputConnectorVisualRect;                 var connectorContent = component.IsInversion ? inversionConnectorDirectionContent : connectorDirectionContent;                 var connectorPointRect = component.IsInversion ? inputConnectorPointRect : outputConnectorPointRect;                  widgetVirtualRect = component.IsInversion ? inputConnectorForExternalVirtualRect : outputConnectorForExternalVirtualRect;                  DrawConnector(connectorVisualRect, connectorPointRect, VLECommon.Setting.ColorOutputPoint, connectorContent);                 DrawOutputPointName(outputNameRect);             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u0420\u0438\u0441\u0443\u0435\u043c \u0441\u0432\u044f\u0437\u0438<\/h2>\n<p>\u0412 \u043e\u0441\u043d\u043e\u0432\u0435 \u043a\u043e\u0434\u0430 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 \u043b\u0435\u0436\u0438\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>ILink<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public interface ILink     {         string Id { get; }          ILogicWidget SourceComponent { get; }         ILogicWidget TargetComponent { get; }          string OutputPoint { get; }         string InputPoint { get; }          bool IsSelected { get; }         bool IsCorrupted { get; }          int CallOrder { get; set; }         Color LinkColor { get; set; }         bool IsActive { get; set; }          void Draw(bool lockMouse);         void DrawTracertLinkData();         void Select(bool state);         bool Contains(Vector2 position);         void MakeTracert(bool state, string data);     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p><strong>SourceComponent<\/strong>, <strong>TargetComponent<\/strong> \u2013 \u0432\u0438\u0434\u0436\u0435\u0442\u044b \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u0441\u0432\u044f\u0437\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>OutputPoint<\/strong>, <strong>InputPoint<\/strong> \u2013 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0432\u044b\u0445\u043e\u0434\u043d\u043e\u0439 \u0438 \u0432\u0445\u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u0435\u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>IsCorrupted<\/strong> \u2013 \u0444\u043b\u0430\u0433, \u0433\u043e\u0432\u043e\u0440\u044f\u0449\u0438\u0439 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u0432\u044f\u0437\u044c \u043d\u0435\u043b\u044c\u0437\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c (\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0441\u0432\u044f\u0437\u0438).<\/p>\n<\/li>\n<li>\n<p><strong>CallOrder<\/strong> \u2013 \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u0432\u044f\u0437\u0438, \u0435\u0441\u043b\u0438 \u0441\u0432\u044f\u0437\u0435\u0439 \u0432\u044b\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0438\u0437 \u043e\u0434\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e (\u043d\u043e\u043c\u0435\u0440\u0430 \u043c\u043e\u0436\u0435\u0442 \u043d\u0435 \u0431\u044b\u0442\u044c, \u0442\u043e\u0433\u0434\u0430 \u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0440\u0430\u0432\u043d\u043e -1).<\/p>\n<\/li>\n<li>\n<p><strong>DrawTracertLinkData<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445. \u0412\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0441\u0432\u044f\u0437\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u043d \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e, \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>Contains<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f, \u0447\u0442\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043b\u0438\u043d\u0438\u0438 \u0441\u0432\u044f\u0437\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>MakeTracert<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441\u0432\u044f\u0437\u0438 (\u0441\u043c. \u0440\u0430\u0437\u0434\u0435\u043b \u043e\u0442\u043b\u0430\u0434\u043a\u0430).<\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043b\u0430\u0441\u0441 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<details class=\"spoiler\">\n<summary>\u041e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public class VLELink : ILink     {         public string Id { get; }          public ILogicWidget SourceComponent => _sourceComponent as ILogicWidget;         public ILogicWidget TargetComponent => _targetComponent as ILogicWidget;          public int CallOrder         {             get => _callOrder;             set             {                 _callOrder = value;                  VLECommon.CurrentLogic.Links.ModifyLinkByLogic(Id, _callOrder);                 VLECommon.UnsavedChanges++;             }         }          public Color LinkColor         {             get => _linkColor;             set             {                 _linkColor = value;                  VLECommon.CurrentLogic.Links.ModifyLinkByLogic(Id, _linkColor);                 VLECommon.UnsavedChanges++;             }         }          public bool IsActive         {             get => _isActive;             set             {                 _isActive = value;                  VLECommon.CurrentLogic.Links.ModifyLinkByLogic(Id, _isActive);                 VLECommon.UnsavedChanges++;             }         }          public string OutputPoint { get; }         public string InputPoint { get; }         public bool IsSelected { get; private set; } = false;         public bool IsCorrupted { get; private set; } = false;          private bool _isActive = true;         private bool _tracert;          private readonly List&lt;string> _tracertDataList = new List&lt;string>();         private Vector2 _tracertDataScrollPosition = Vector2.zero;          private Rect _linkDataRect = new Rect(0f, 0f, 200f, 0f);         private Rect _linkDataViewRect = new Rect(0f, 0f, 200f, 100f);          private bool _pulsation;         private float _pulsationTime;          private IComponentWidget _sourceComponent;         private IComponentWidget _targetComponent;          private int _callOrder = -1;         private Color _linkColor;          private Vector2 _source;         private Vector2 _target;         private Vector2 _sourceTan;         private Vector2 _targetTan;          private GUIStyle _tracertGUIStyle;         private GUIStyle _orderSetGUIStyle;         private GUIStyle _orderViewGUIStyle;          private LogicStorage.LinksStorage.LinkData _linkStorage;          private const string _DATA_FMT_STR = \"&lt;color=yellow>&lt;b>Data&lt;\/b>&lt;\/color>: &lt;color=white>[{0}]&lt;\/color>\";          public VLELink(LogicStorage.LinksStorage.LinkData linkStorage, IComponentWidget source, IComponentWidget target)         {             _linkStorage = linkStorage;              _sourceComponent = source;             _targetComponent = target;              OutputPoint = linkStorage.OutputPoint;             InputPoint = linkStorage.InputPoint;              Id = linkStorage.Id;             _callOrder = linkStorage.CallOrder;              _isActive = _linkStorage.IsActive;              Color inctanceColor;              if (!string.IsNullOrEmpty(linkStorage.Color) &amp;&amp; ColorUtility.TryParseHtmlString(linkStorage.Color, out inctanceColor))             {                 _linkColor = inctanceColor;             }             else             {                 _linkColor = VLECommon.Setting.ColorLink;             }         }          public void Draw(bool lockMouse)         {             RegisterStyle();              var sourceRect = _sourceComponent.GetOutputPointRect(OutputPoint);             var targetRect = _targetComponent.GetInputPointRect(InputPoint);              if (sourceRect != Rect.zero &amp;&amp; targetRect != Rect.zero)             {                 _source = new Vector2(sourceRect.xMax - 2f, sourceRect.center.y - 1f);                 _target = new Vector2(targetRect.xMin + 2f, targetRect.center.y - 1f);                  if (string.IsNullOrEmpty(_linkStorage.Color))                 {                     _linkColor = VLECommon.Setting.ColorLink;                 }                  _linkColor.a = _isActive ? 1f : 0.5f;                  VLEditorUtils.DrawBezierLink(_source,                                              _target,                                              ref _sourceTan,                                              ref _targetTan,                                              _sourceComponent.IsInversion,                                              _targetComponent.IsInversion,                                              _isActive ? (_tracert ? GetTracertColor() : _linkColor) : Color.gray,                                              (IsSelected || _tracert) ? 5f : 2f);                  DrawLinkOrderData();                  HandleEvent(lockMouse);             }             else             {                 IsCorrupted = true;             }         }          private void HandleEvent(bool lockMouse)         {             var ev = Event.current;              if (VLECommon.IsMultipleLinks || ev.control || lockMouse) return;              if (ev.type == EventType.MouseDown &amp;&amp; ev.button == 0)             {                 if (Contains(ev.mousePosition))                 {                     IsSelected = true;                      if (VLECommon.SelectedLink != this)                     {                         if (VLECommon.SelectedLink != null)                         {                             VLECommon.SelectedLink.Select(false);                         }                          VLECommon.SelectedLink = this;                     }                 }                 else                 {                     IsSelected = false;                      if (VLECommon.SelectedLink == this)                     {                         VLECommon.SelectedLink = null;                     }                 }             }         }          public bool Contains(Vector2 position) => HandleUtility.DistancePointBezier(position, _source, _target, _sourceTan, _targetTan) &lt; 5f;                 public void MakeTracert(bool state, string data)         {             if (_tracert &amp;&amp; state)             {                 if (!_pulsation)                 {                     _pulsation = true;                     _pulsationTime = VLETime.Time;                 }             }              _tracert = state;              _sourceComponent.MakeTracert(_tracert, false);             _targetComponent.MakeTracert(_tracert, true);              if (_tracert)             {                 if (data.Length != 0)                 {                                         _tracertDataList.Add(_DATA_FMT_STR.Fmt(data));                 }             }             else             {                 _tracertDataList.Clear();                 _tracertDataScrollPosition = Vector2.zero;             }         }          public void Select(bool state)         {             IsSelected = state;              if (VLECommon.SelectedLinks.Contains(this))             {                 if (!IsSelected)                 {                     VLECommon.SelectedLinks.Remove(this);                 }             }             else             {                 if (IsSelected)                 {                     VLECommon.SelectedLinks.Add(this);                 }             }         }          public void DrawTracertLinkData()         {             if (_tracert &amp;&amp; IsSelected &amp;&amp; (_tracertDataList.Count > 0))             {                 var target = GetMiddlePoint();                  _linkDataRect.width = 250f;                 _linkDataViewRect.width = _linkDataRect.width;                  target.x = Mathf.Floor(target.x - _linkDataRect.width \/ 2f);                 target.y = Mathf.Floor(target.y);                  _linkDataRect.position = target;                 _linkDataViewRect.position = target;                  var tracertData = PrepareTracertData().ToString();                  if (tracertData.Length > 15000)                 {                     _tracertDataList.RemoveAt(0);                      tracertData = PrepareTracertData().ToString();                 }                  _linkDataRect.height = Mathf.Floor(_tracertGUIStyle.CalcHeight(new GUIContent(tracertData), _linkDataRect.width));                  _tracertDataScrollPosition = GUI.BeginScrollView(_linkDataViewRect, _tracertDataScrollPosition, _linkDataRect, GUIStyle.none, GUI.skin.verticalScrollbar);                  var handleRect = new Rect(_linkDataRect);                  handleRect.width -= 2f;                 handleRect.height -= 1f;                 handleRect.x += 1f;                 handleRect.y += 1f;                  Handles.DrawSolidRectangleWithOutline(handleRect, Color.gray, Color.black);                  GUI.Label(_linkDataRect, tracertData, _tracertGUIStyle);                  GUI.EndScrollView();             }         }          private void DrawLinkOrderData()         {             void prepareLinkDataRect(float width, float height)             {                 _linkDataRect.width = width;                 _linkDataRect.height = height;                  var linkDataRectPosition = _source;                  linkDataRectPosition.y = _source.y + (_target.y - _source.y) \/ 2f - _linkDataRect.height;                  if ((!_sourceComponent.IsInversion &amp;&amp; !_targetComponent.IsInversion) ||                     (_sourceComponent.IsInversion &amp;&amp; _targetComponent.IsInversion))                 {                     linkDataRectPosition.x += (_target.x - _source.x) \/ 2f;                 }                 else if (_sourceComponent.IsInversion)                 {                     if (_target.x &lt;= _source.x)                     {                         linkDataRectPosition.x = _target.x - width \/ 2f;                     }                     else                     {                         linkDataRectPosition.x = _source.x - width \/ 2f;                     }                 }                 else if (_targetComponent.IsInversion)                 {                     if (_target.x > _source.x)                     {                         linkDataRectPosition.x += (_target.x - _source.x) \/ 2f;                     }                 }                  _linkDataRect.position = linkDataRectPosition;             };              if (!_tracert &amp;&amp; IsSelected &amp;&amp; !EditorApplication.isPlayingOrWillChangePlaymode &amp;&amp; !VLECommon.IsMultipleLinks)             {                 var ordersValue = new List&lt;string>();                 var ordersCount = VLECommon.CurrentLogic.Links.GetLinks(SourceComponent.Id, OutputPoint).Count;                  if (ordersCount > 1)                 {                     prepareLinkDataRect(50f, 25f);                      for (var i = 0; i &lt; ordersCount; i++)                     {                         ordersValue.Add((i + 1).ToString());                     }                      var newOrder = EditorGUI.Popup(_linkDataRect, _callOrder, ordersValue.ToArray());                      if (newOrder != _callOrder)                     {                         _callOrder = newOrder;                          VLECommon.CurrentLogic.Links.ModifyLinkByLogic(Id, _callOrder);                         VLECommon.UnsavedChanges++;                     }                 }             }             else             {                 var ordersCount = VLECommon.CurrentLogic.Links.GetLinks(SourceComponent.Id, OutputPoint).Count;                  if (ordersCount &lt;= 1)                 {                     if (_callOrder >= 0)                     {                         _callOrder = -1;                          VLECommon.CurrentLogic.Links.ModifyLinkByLogic(Id, _callOrder);                         VLECommon.UnsavedChanges++;                     }                 }                  if (_callOrder >= 0)                 {                     prepareLinkDataRect(75f, 25f);                      EditorGUI.LabelField(_linkDataRect, (_callOrder + 1).ToString(), _orderViewGUIStyle);                 }             }         }          private void RegisterStyle()         {             if (_tracertGUIStyle == null)             {                 _tracertGUIStyle = new GUIStyle(GUI.skin.label);                  _tracertGUIStyle.fontSize = 12;                 _tracertGUIStyle.alignment = TextAnchor.UpperLeft;                 _tracertGUIStyle.wordWrap = true;                 _tracertGUIStyle.richText = true;                  _orderSetGUIStyle = new GUIStyle(EditorStyles.popup);                 _orderSetGUIStyle.alignment = TextAnchor.MiddleLeft;                  _orderViewGUIStyle = new GUIStyle(GUI.skin.label);                  _orderViewGUIStyle.alignment = TextAnchor.MiddleLeft;                 _orderViewGUIStyle.normal.textColor = Color.white;             }         }          private Vector2 GetMiddlePoint() => _source + (_target - _source).normalized * Vector2.Distance(_source, _target) \/ 2f;                 private Color GetTracertColor()         {             var tracertColor = VLECommon.Setting.ColorTracertComplete;             var linkColor = (Color)VLECommon.Setting.ColorLink;              if (_pulsation)             {                 var time = 5f * Mathf.Clamp01(VLETime.Time - _pulsationTime);                  tracertColor = Color.Lerp(linkColor, tracertColor, time);                  if (time >= 1f)                 {                     _pulsation = false;                 }             }              return tracertColor;         }          private StringBuilder PrepareTracertData()         {             var stringBuilder = new StringBuilder();              for (var i = 0; i &lt; _tracertDataList.Count; i++)             {                 var data = _tracertDataList[i];                  if (stringBuilder.Length != 0)                 {                     stringBuilder.Append(\"\\n\");                 }                  stringBuilder.Append(data);             }              return stringBuilder;         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u043c\u043d\u043e\u0433\u043e, \u043d\u043e \u0441\u0430\u043c \u043a\u043e\u0434 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043a\u0430\u043a \u0434\u0440\u043e\u0432\u0430, \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0431\u044b, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u044d\u0442\u043e \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u0441\u0430\u043c\u043e\u0439 \u043b\u0438\u043d\u0438\u0438 \u0441\u0432\u044f\u0437\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <strong>Handles.DrawBezier<\/strong> \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044b\u0439 \u0432 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public static void DrawBezierLink(Vector2 sourcePoint, Vector2 targetPoint, ref Vector2 sourceTan, ref Vector2 targetTan, bool sourceInversion, bool targetIsInversion, Color color, float width = 2f) {     var bendPower = Vector2.up * (targetPoint.x > sourcePoint.x ? 0f : (targetPoint.y - sourcePoint.y) * 0.5f);     var dirTan = Vector2.right * Mathf.Clamp(Mathf.Abs(targetPoint.x - sourcePoint.x), 50f, 200f) * 0.5f;      if (!sourceInversion)     {         sourceTan = sourcePoint + dirTan + bendPower;     }     else     {         sourceTan = sourcePoint - dirTan;     }      if (!targetIsInversion)     {         targetTan = targetPoint - dirTan - bendPower;     }     else     {         targetTan = targetPoint + dirTan;     }      Handles.DrawBezier(sourcePoint, targetPoint, sourceTan, targetTan, color, null, width); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0442\u043e\u0434 \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0432\u044f\u0437\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0444\u0430\u043a\u0442 \u0438\u043d\u0432\u0435\u0440\u0441\u0438\u0438 \u0442\u043e\u0447\u0435\u043a \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435.<\/p>\n<h2>\u0418\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440<\/h2>\n<p>\u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435 <strong>Unity<\/strong> \u043f\u0443\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0447\u0435\u0440\u0435\u0437 <strong>CustomEditor<\/strong>. \u0412 \u0446\u0435\u043b\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0442\u0440\u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438:<\/p>\n<ul>\n<li>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442.<\/p>\n<h3>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity<\/h3>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"301\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/544\/62b\/073\/54462b073f3314a0b45d07ca6a3c575b.png\" data-width=\"470\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u0430, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0449\u0435\u0433\u043e <strong>CustomEditor<\/strong> \u0434\u043b\u044f <strong>VLObject<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     [CustomPropertyDrawer(typeof(VLObject), true)]     public class VLEObjectEditor : PropertyDrawer     {         private const string _ID_STR = \"_id\";         private const string _GAMEOBJECT_STR = \"GameObject\";         public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)         {             var labelRect = new Rect(position.x, position.y + 2f, position.width, 20f);             var objectLinkRect = new Rect(position.x + 4f, position.y + 25f, position.width - 4f, 17f);             var componentsPopupRect = new Rect(position.x + 2f, position.y + 45f, position.width - 4f, 20f);             var obectReferenseType = typeof(UnityEngine.Object);             var attributes = fieldInfo.GetCustomAttributes(typeof(TypeConstraintAttribute), true);             var height = 64f;              if (attributes.Length > 0)             {                 var attribute = attributes[0] as TypeConstraintAttribute;                  obectReferenseType = attribute.Constraint;                  height = 46f;             }              var propertyRect = new Rect(position.x, position.y, position.width, height);             var areaRect = new Rect(position.x, position.y, position.width, height);              EditorGUI.BeginProperty(propertyRect, label, property);              var guiStyle = new GUIStyle(EditorStyles.label);              guiStyle.fontSize = 12;             guiStyle.fontStyle = FontStyle.Bold;             guiStyle.alignment = TextAnchor.MiddleCenter;             guiStyle.normal.textColor = Color.gray;              GUI.Box(areaRect, GUIContent.none);              EditorGUI.LabelField(labelRect, property.displayName, guiStyle);              var VLEController = VLECommon.CurrentLogicController;             var idField = property.FindPropertyRelative(_ID_STR);              var referenceObj = VLEController.GetObject(idField.stringValue);             var newReferenceObj = EditorGUI.ObjectField(objectLinkRect, string.Empty, referenceObj, obectReferenseType, true);              if (referenceObj != newReferenceObj)             {                 SaveObjectLink(idField, newReferenceObj);             }              if (attributes.Length == 0 &amp;&amp; newReferenceObj != null &amp;&amp; (newReferenceObj is GameObject || newReferenceObj is Component))             {                 var gameObject = (newReferenceObj is GameObject) ? (GameObject)newReferenceObj : ((Component)newReferenceObj).gameObject;                 var components = gameObject.GetComponents(typeof(Component));                  var componentNames = new List&lt;string>();                  componentNames.Add(_GAMEOBJECT_STR);                  for (var i = 0; i &lt; components.Length; i++)                 {                     componentNames.Add(components[i].GetType().Name);                 }                  var index = EditorGUI.Popup(componentsPopupRect, string.Empty, -1, componentNames.ToArray());                  if (index > 0)                 {                     var component = components[index - 1];                      SaveObjectLink(idField, component);                 }                 else if (index == 0)                 {                     SaveObjectLink(idField, gameObject);                 }             }              EditorGUI.EndProperty();         }          private void SaveObjectLink(SerializedProperty idProperty, UnityEngine.Object obj)         {             var vleController = VLECommon.CurrentLogicController;             var oldValue = idProperty.stringValue;              idProperty.stringValue = vleController.SetObject(oldValue, obj);              VLECommon.UnsavedChanges++;         }          public override float GetPropertyHeight(SerializedProperty property, GUIContent label) => base.GetPropertyHeight(property, label) + 50f;             } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0437\u0434\u0435\u0441\u044c:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0431\u043e\u0440\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <strong>Unity<\/strong> \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0432 \u0441\u0441\u044b\u043b\u043a\u0443, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u0435 (\u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a). \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <strong>GetComponents(typeof(Component))<\/strong>. \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434, \u0442\u043e \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <strong>GameObject<\/strong> \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u0430 <strong>TypeConstraint<\/strong>. \u0414\u0430\u043d\u043d\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u0432 <strong>VLObject<\/strong> \u0441\u0441\u044b\u043b\u043e\u043a \u043f\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u043c\u0443 \u0442\u0438\u043f\u0443. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0440\u0435\u0444\u043b\u0435\u043a\u0441\u0438\u044e <strong>fieldInfo.GetCustomAttributes(typeof(TypeConstraintAttribute), true)<\/strong><\/p>\n<\/li>\n<\/ol>\n<h3>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043b\u043e\u0433\u0438\u043a\u0438<\/h3>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"403\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/eed\/e02\/47d\/eede0247d98a15ffc282a1cce4b3ec2a.png\" data-width=\"473\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u0432\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0432 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u0434\u0430, \u043d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0441 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c\u044e <strong>VARIABLE_LINK<\/strong>, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <strong>generic<\/strong>-\u043a\u043b\u0430\u0441\u0441\u043e\u043c \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043b\u043e\u0433\u0438\u043a\u0438, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 <strong>generic<\/strong>-\u043a\u043b\u0430\u0441\u0441\u043e\u043c <strong>Variable<\/strong> (\u0441\u043c. \u0432\u0442\u043e\u0440\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043f\u0440\u043e \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438). \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043e\u0431\u0430 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u0430 \u044d\u0442\u043e <strong>generic\u2019<\/strong>\u0438, \u0442\u043e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0447\u0435\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0442\u0438\u043f\u044b \u0438\u0445 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u043b\u0438, \u0442. \u0435. \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0441\u0441\u044b\u043b\u043a\u0438, \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0442\u0438\u043f\u0443, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0435 \u043a\u043b\u0430\u0441\u0441\u0430 <strong>VARIABLE_LINK<\/strong>. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u0434 \u0438 \u043f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLELogicComponentCustomEditor     {         private class VariableData         {             public string Id;             public string Name;             public Type CoreType;              public VariableData(string id, string name, Type coreType)             {                 Id = id;                 Name = name;                 CoreType = coreType;             }         }          private readonly List&lt;VariableData> _variableList = new List&lt;VariableData>();          private readonly IDictionary&lt;string, List&lt;string>> _variableNamesByLinkName = new Dictionary&lt;string, List&lt;string>>();         private readonly IDictionary&lt;string, int> _variableNameSelected = new Dictionary&lt;string, int>();         private readonly IDictionary&lt;string, string> _variableLinksStorage = new Dictionary&lt;string, string>();          private void LoadVariablesList()         {             _variableList.Clear();              var variables = VLECommon.CurrentLogic.Components.Items.FindAll(data => typeof(Core.Variable).IsAssignableFrom(AssemblyHelper.GetAssemblyType(data.Assembly, data.Type)));              variables.SafeForEach(variable =>             {                 var variableType = AssemblyHelper.GetAssemblyType(variable.Assembly, variable.Type);                 var variableDefinition = (ComponentDefinitionAttribute)variableType.GetCustomAttributes(typeof(ComponentDefinitionAttribute), true)[0];                  _variableList.Add(new VariableData(variable.Id,                                                   (variable.InstanceName == string.Empty) ? variableDefinition.Name : variable.InstanceName,                                                   variableType.BaseType.GetGenericArguments()[0]));             });                    }          private void UpdateVariableLinks()         {             GetVariableLinks();             RestoreVariableLinks();         }          private void GetVariableLinks()         {             _variableNamesByLinkName.Clear();              var variableLinkFields = VLECommon.SelectedWidget.InstanceType.GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);              for (var i = 0; i &lt; variableLinkFields.Length; i++)             {                 var fieldInfo = variableLinkFields[i];                  if (fieldInfo.FieldType.IsGenericType &amp;&amp;                     fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(VARIABLE_LINK&lt;>))                 {                     var variableDatas = _variableList.FindAll(data => data.CoreType == fieldInfo.FieldType.GetGenericArguments()[0]);                                         var allowedVariableNames = new List&lt;string>() { \"None\" };                      for (var j = 0; j &lt; variableDatas.Count; j++)                     {                         var variableData = variableDatas[j];                          allowedVariableNames.Add(variableData.Name);                     }                      _variableNamesByLinkName.Add(fieldInfo.Name, allowedVariableNames);                 }             }         }          private void RestoreVariableLinks()         {             _variableNameSelected.Clear();             _variableLinksStorage.Clear();              foreach (var variableName in _variableNamesByLinkName.Keys)             {                 _variableNameSelected.Add(variableName, 0);             }              var componentVariableLinks = VLECommon.CurrentLogic.Links.GetVariableLinks(VLECommon.SelectedWidget.Id);              if (componentVariableLinks.Count > 0)             {                 for (var i = 0; i &lt; componentVariableLinks.Count; i++)                 {                     var linkData = componentVariableLinks[i];                      if (_variableNameSelected.ContainsKey(linkData.variableName))                     {                         var targetVariable = _variableList.Find((data) => data.Id == linkData.TargetComponent);                                                  if (targetVariable != null)                         {                             _variableNameSelected[linkData.variableName] = _variableNamesByLinkName[linkData.variableName].IndexOf(targetVariable.Name);                              _variableLinksStorage.Add(linkData.variableName, linkData.Id);                         }                         else                         {                             Debug.LogWarning($\"[uViLEd]: not found variable component [TargetComponent = {linkData.TargetComponent}; VariableName = {linkData.variableName}]\");                         }                     }                 }             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<ul>\n<li>\n<p><strong>LoadVariablesList<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>GetVariableLinks<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u0441\u0441\u044b\u043b\u043a\u0430\u0445 \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0432 \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>RestoreVariableLinks<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043f\u0435\u0440\u0435\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 \u043a\u043e\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435, \u0442\u043e \u043e\u043d\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 <strong>EditorGUILayout.Popup<\/strong> (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u0441\u043c\u043e\u0442\u0440\u0438 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0440\u0430\u0437\u0434\u0435\u043b\u0435).<\/p>\n<h3>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438<\/h3>\n<p>\u041a\u0430\u043a \u0431\u044b\u043b\u043e \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445, \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u043c \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435 <strong>Unity<\/strong>, \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0432 \u0438\u0445 \u043e\u0441\u043d\u043e\u0432\u0435 \u043b\u0435\u0436\u0438\u0442 \u043a\u043b\u0430\u0441\u0441 <strong>ScriptableObject<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438. \u041f\u043e\u043c\u0438\u043c\u043e \u044d\u0442\u043e\u0433\u043e, \u0441\u0442\u043e\u0438\u0442 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0438 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u044b \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <strong>CustomPropertyDrawer<\/strong> \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     [CustomEditor(typeof(LogicComponent), true)]     public partial class VLELogicComponentCustomEditor : UnityEditor.Editor     {                 private GUIStyle _headerStyle,                          _descriptionStyle,                          _variableLinkHeaderStyle,                          _variableLinkDeprecetedStyle;          private bool _prepared,                      _unsavedChangesCounted,                              _variableInitialized;          protected override void OnHeaderGUI()         {             if (VLECommon.SelectedWidget == null) return;              UpdateGUIStyle();              EditorGUILayout.BeginHorizontal();             {                 _headerStyle.normal.textColor = VLECommon.SelectedWidget.WidgetColor;                 EditorGUILayout.LabelField(VLECommon.SelectedWidget.Name, _headerStyle, GUILayout.ExpandWidth(true));                  EditorGUIWithChangeCheck(() =>                 {                     VLECommon.SelectedWidget.WidgetColor = EditorGUILayout.ColorField(VLECommon.SelectedWidget.WidgetColor, GUILayout.MaxWidth(50f));                 });             }             EditorGUILayout.EndHorizontal();              EditorGUILayout.LabelField(VLECommon.SelectedWidget.Description, _descriptionStyle, GUILayout.ExpandWidth(true));         }          public override void OnInspectorGUI()         {             if (VLECommon.SelectedWidget == null) return;              if (!_variableInitialized)             {                 LoadVariablesList();                 UpdateVariableLinks();                  _variableInitialized = true;             }              if (!EditorApplication.isCompiling &amp;&amp; !EditorApplication.isPlayingOrWillChangePlaymode)             {                 ComponentInspector();             }             else             {                 if (EditorApplication.isCompiling)                 {                     GUILayout.Label(\"wait for compiling...\");                 }                 else if (EditorApplication.isPlayingOrWillChangePlaymode)                 {                     GUILayout.Label(\"you can not change settings in the Play mode...\");                 }             }         }          private void ComponentInspector()         {             EditorGUILayout.BeginHorizontal();             {                 EditorGUILayout.LabelField(\"Name\", GUILayout.MaxWidth(146f));                  EditorGUIWithChangeCheck(() => VLECommon.SelectedWidget.Name = EditorGUILayout.TextField(VLECommon.SelectedWidget.Name));             }             EditorGUILayout.EndHorizontal();              EditorGUILayout.BeginHorizontal();             {                 EditorGUILayout.LabelField(\"Comment\", GUILayout.MaxWidth(146f));                                  EditorGUIWithChangeCheck(() => VLECommon.SelectedWidget.Comment = EditorGUILayout.TextArea(VLECommon.SelectedWidget.Comment));                             }             EditorGUILayout.EndHorizontal();              EditorGUILayout.Space();             EditorGUILayout.LabelField(\"Component Parameters\", _variableLinkHeaderStyle, GUILayout.ExpandWidth(true));             EditorGUILayout.Space();              serializedObject.Update();              var property = serializedObject.GetIterator();              property.NextVisible(true);              while (property.NextVisible(false))             {                 EditorGUIWithChangeCheck(() =>                 {                     EditorGUILayout.PropertyField(property, true);                 });             }              if (_variableNamesByLinkName.Count > 0)             {                 EditorGUILayout.Space();                 EditorGUILayout.LabelField(\"Variable Links\", _variableLinkHeaderStyle, GUILayout.ExpandWidth(true));                 EditorGUILayout.Space();             }              foreach (var variableLinkName in _variableNamesByLinkName.Keys)             {                 var displayedNames = _variableNamesByLinkName[variableLinkName].ToArray();                  if (displayedNames.Length > 0)                 {                     EditorGUIWithChangeCheck(() => _variableNameSelected[variableLinkName] = EditorGUILayout.Popup(variableLinkName, _variableNameSelected[variableLinkName], displayedNames));                                     }                 else                 {                     EditorGUILayout.LabelField(variableLinkName + \" [impossible setup link, no variables in logic]\", _variableLinkDeprecetedStyle);                 }             }              SaveChanges();         }          private void SaveChanges()         {             serializedObject.ApplyModifiedProperties();              VLECommon.CurrentLogic.Components.ModiftyComponent(VLECommon.SelectedWidget.Id, JsonUtility.ToJson(VLECommon.SelectedWidget.Instance));              if (!(VLECommon.SelectedWidget is IComponentWidget))             {                 var variableData = _variableList.Find(data => data.Id == VLECommon.SelectedWidget.Id);                                  variableData.Name = VLECommon.SelectedWidget.Name;             }              foreach (var variableLinkName in _variableNameSelected.Keys)             {                 var variableIndex = _variableNameSelected[variableLinkName];                  if (variableIndex > 0)                 {                     var variableName = _variableNamesByLinkName[variableLinkName][variableIndex];                     var variableData = _variableList.Find(data => data.Name == variableName);                                          if (_variableLinksStorage.ContainsKey(variableLinkName))                     {                         VLECommon.CurrentLogic.Links.ModifyLink(_variableLinksStorage[variableLinkName],                                                                 VLECommon.SelectedWidget.Id,                                                                 variableData.Id,                                                                 variableLinkName);                     }                     else                     {                         var newLink = VLECommon.CurrentLogic.Links.AddLink(VLECommon.SelectedWidget.Id, variableData.Id, variableLinkName);                          _variableLinksStorage.Add(variableLinkName, newLink.Id);                     }                 }                 else                 {                     if (_variableLinksStorage.ContainsKey(variableLinkName))                     {                         VLECommon.CurrentLogic.Links.ModifyLink(_variableLinksStorage[variableLinkName], string.Empty, string.Empty, string.Empty);                          _variableLinksStorage.Remove(variableLinkName);                     }                 }             }                          (VLECommon.SelectedWidget as IParameterContainer)?.UpdateParameterValues();                     }          private void EditorGUIWithChangeCheck(Action guiDraw)         {             EditorGUI.BeginChangeCheck();              guiDraw();              if (EditorGUI.EndChangeCheck())             {                 if (!_unsavedChangesCounted || VLECommon.UnsavedChanges == 0)                 {                     VLECommon.UnsavedChanges++;                      _unsavedChangesCounted = true;                 }             }         }          private void UpdateGUIStyle()         {             if (_prepared) return;              _headerStyle = new GUIStyle(GUI.skin.box);             _headerStyle.fontStyle = FontStyle.Bold;             _headerStyle.fontSize = 18;              _descriptionStyle = new GUIStyle(GUI.skin.box);             _descriptionStyle.normal.textColor = Color.gray;              _variableLinkHeaderStyle = new GUIStyle(GUI.skin.box);             _variableLinkHeaderStyle.normal.textColor = Color.gray;             _variableLinkHeaderStyle.fontStyle = FontStyle.Bold;              _variableLinkDeprecetedStyle = new GUIStyle(GUI.skin.label);             _variableLinkDeprecetedStyle.normal.textColor = Color.red;              _prepared = true;         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0432\u0442\u043e\u0440\u044e\u0441\u044c, \u043a\u0430\u043a \u0438 \u0440\u0430\u043d\u0435\u0435, \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043e\u0434\u043d\u0430\u043a\u043e \u0437\u0434\u0435\u0441\u044c \u0441\u0442\u043e\u0438\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0441\u043e\u0431\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u043e\u043f\u0438\u0441\u0430\u043b \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0430: <\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432, \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0435 \u043b\u043e\u0433\u0438\u043a\u0435. \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u043e\u0432 <strong>EditorGUI.BeginChangeCheck()<\/strong> \u0438 <strong>EditorGUI.EndChangeCheck()<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044b \u0432 \u043c\u0435\u0442\u043e\u0434 <strong>EditorGUIWithChangeCheck<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0432\u043e\u0434 \u0432\u0441\u0435\u0445 \u043f\u0440\u043e\u043f\u0435\u0440\u0442\u0435\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u201c\u043a\u0430\u043a \u0435\u0441\u0442\u044c\u201d \u2013 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u0441\u0442\u0432 <strong>Unity<\/strong>. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043f\u0435\u0440\u0435\u0431\u043e\u0440\u0430 \u0441\u0432\u043e\u0439\u0441\u0442\u0432:<\/p>\n<pre><code class=\"cs\">serializedObject.Update();  var property = serializedObject.GetIterator();  property.NextVisible(true);  while (property.NextVisible(false)) {     EditorGUIWithChangeCheck(() =>     {         EditorGUILayout.PropertyField(property, true);     }); }<\/code><\/pre>\n<\/li>\n<\/ol>\n<h2>\u041a\u0430\u0442\u0430\u043b\u043e\u0433<\/h2>\n<p>\u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 \u043e\u043a\u043d\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a\u043e \u0432\u0441\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043e\u0437\u0434\u0430\u044e\u0442 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u044b. \u041f\u043e\u043c\u0438\u043c\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u0438 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432 \u043b\u043e\u0433\u0438\u043a\u0443 \u0447\u0435\u0440\u0435\u0437 \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435. \u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u043a\u043d\u0430 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430:<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"622\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/6e1\/eac\/a55\/6e1eaca55455e9f2e71dd6e0be7637a4.png\" data-width=\"407\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432\u0441\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public sealed partial class VLECatalog     {         public abstract class CatalogBase         {             public string Name { get; private set; }             public CatalogBase(string name) => Name = name;                     }          public sealed class CatalogComponent : CatalogBase         {             public string Tooltip { get; private set; }             public Type ComponentType { get; private set; }             public Color ComponentColor { get; private set; }              public CatalogComponent(string name, string tooltip, Type type, Color color) : base(name)             {                 Tooltip = tooltip;                 ComponentType = type;                 ComponentColor = color;             }         }          public sealed class CatalogFolder : CatalogBase         {             public CatalogFolder(string name) : base(name) { }              public readonly List&lt;CatalogBase> SubFolders = new List&lt;CatalogBase>();             public readonly List&lt;CatalogBase> Components = new List&lt;CatalogBase>();         }          public CatalogBase Catalog { get; } = new CatalogFolder(\"Root\");          private readonly IList&lt;Type> _components = new List&lt;Type>();         private readonly IList&lt;Type> _variables = new List&lt;Type>();          public VLECatalog()         {             LoadAssembly();              FillCatalog(_components);             FillCatalog(_variables);         }          private void LoadAssembly()         {             var allAssembliesDomain = AppDomain.CurrentDomain.GetAssemblies();              foreach (var assembly in allAssembliesDomain)             {                 if (assembly.FullName.Contains(\"System\") ||                     assembly.FullName.Contains(\"UnityEditor\") ||                     assembly.FullName.Contains(\"UnityEngine\") ||                     assembly.FullName.Contains(\"uViLEdEditor\"))                 {                     continue;                 }                 else                 {                     foreach (var checkedType in assembly.GetTypes())                     {                         if (checkedType.IsAbstract) continue;                          if (checkedType != typeof(Core.Variable) &amp;&amp; checkedType != typeof(Core.Variable&lt;>) &amp;&amp; checkedType != typeof(Core.LogicComponent))                         {                             if (typeof(Core.Variable).IsAssignableFrom(checkedType))                             {                                 if (!_variables.Contains(checkedType))                                 {                                     _variables.Add(checkedType);                                 }                             }                             else if (typeof(Core.LogicComponent).IsAssignableFrom(checkedType))                             {                                 if (!_components.Contains(checkedType))                                 {                                     _components.Add(checkedType);                                 }                             }                         }                     }                 }             }         }          private void FillCatalog(IList&lt;Type> components)         {             void addAndSort(List&lt;CatalogBase> folders, CatalogBase subFolder)             {                 folders.Add(subFolder);                 SortCatalogByName(folders);             }              foreach (var component in components)             {                 var componentData = CreateCatalogComponent(component);                 var subFolderNames = componentData.Path.Split('\/');                  if (subFolderNames.Length > 0)                 {                     var folders = (Catalog as CatalogFolder).SubFolders;                      for (var i = 0; i &lt; subFolderNames.Length; i++)                     {                         var subFolderName = subFolderNames[i];                         var subFolder = (CatalogFolder)GetCatalog(subFolderNames[i], folders);                          if (subFolder == null)                         {                             subFolder = new CatalogFolder(subFolderName);                              addAndSort(folders, subFolder);                         }                          if (i == subFolderNames.Length - 1)                         {                             if (GetCatalog(componentData.Component.Name, subFolder.Components) == null)                             {                                 addAndSort(subFolder.Components, componentData.Component);                             }                             else                             {                                 Debug.LogWarning($\"[uViLEd]: catalog duplicate logic component in folder [name = {componentData.Component.Name}, type = {componentData.Component.ComponentType}]\");                             }                         }                         else                         {                             folders = subFolder.SubFolders;                         }                     }                 }                 else                 {                     (Catalog as CatalogFolder)?.Components.Add(componentData.Component);                 }             }         }          private (string Path, CatalogComponent Component) CreateCatalogComponent(Type componentType)         {             var path = string.Empty;             var catalogName = componentType.Name;             var tooltip = componentType.Name;             var color = (Color)VLECommon.Setting.ColorComponent;              var attributes = componentType.GetCustomAttributes(typeof(ComponentDefinitionAttribute), true);              if (attributes.Length > 0)             {                 var attributeData = (ComponentDefinitionAttribute)attributes[0];                  path = attributeData.Path;                 catalogName = attributeData.Name;                 tooltip = attributeData.Tooltip;                  if (!ColorUtility.TryParseHtmlString(attributeData.Color, out color))                 {                     color = VLECommon.Setting.ColorComponent;                 }             }              var catalogComponent = new CatalogComponent(catalogName, tooltip, componentType, color);              return (path, catalogComponent);         }     }  public IList&lt;CatalogBase> SearchComponentByContext(string context)         {             var returnedValue = new List&lt;CatalogBase>();             var subFolders = (Catalog as CatalogFolder).SubFolders;              subFolders.ForEach(folder => SearchComponentInFolder(context, folder, returnedValue));              return returnedValue;         }          private void SearchComponentInFolder(string context, CatalogBase rootFolder, List&lt;CatalogBase> collection)         {             var catalogFolder = (CatalogFolder)rootFolder;             var lowerContext = context.ToLower();              var findedComponent = from component in catalogFolder.Components                                   where component.Name.Substring(0, Mathf.Clamp(context.Length, 0, component.Name.Length)).ToLower() == lowerContext                                   select component;              collection.AddRange(findedComponent);              catalogFolder.SubFolders.ForEach(subfolder => SearchComponentInFolder(context, subfolder, collection));         }          private CatalogBase GetCatalog(string name, List&lt;CatalogBase> components) => components.Find((data) => data.Name == name);                              private void SortCatalogByName(List&lt;CatalogBase> folders) => folders.Sort((one, two) => one.Name.CompareTo(two.Name)); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0418\u0442\u0430\u043a, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435:<\/p>\n<ol>\n<li>\n<p>\u041f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0431\u043e\u0440\u043e\u043a \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0432\u0441\u0435\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043d\u0430\u0441\u043b\u0435\u0434\u043d\u0438\u043a\u043e\u0432 <strong>LogicComponent<\/strong> \u0438 <strong>Variable<\/strong> (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 <strong>generic<\/strong>).<\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u043c \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u043e \u0438\u043c\u0435\u043d\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0418\u043c\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0435\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0438\u0435, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0446\u0432\u0435\u0442 \u0438 \u0442. \u043f. \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0438\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430 <strong>ComponentDefinition<\/strong>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u043a\u043e\u0434 \u043e\u043a\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043a\u0430\u0442\u0430\u043b\u043e\u0433, \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043d\u0438\u043c \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f:<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLECatalogWindow : VLEWindowEditor     {         private VLECatalog _vleCatalog;                  private const string _COMPONENTS_CATALOG_STR = \"Components Catalog\";         private const string _CAN_NOT_ADD_STR = \"you can not add components in the Play mode...\";         private const string _WAIT_COMPILINIG_STR = \"wait for compiling...\";          public static void Open() => CreateWindow&lt;VLECatalogWindow>(_COMPONENTS_CATALOG_STR);                 void OnEnable()         {             _vleCatalog = new VLECatalog();              LoadCatalogState();         }          void OnDisable()         {             _prepared = false;              VLECommon.ClearSetting();         }          void OnGUI()         {             if (EditorApplication.isPlayingOrWillChangePlaymode)             {                 GUILayout.Label(_CAN_NOT_ADD_STR);             }             else             {                 GUILayout.BeginVertical();                 {                     GUILayout.Space(5f);                      if (!Context())                     {                         if (!EditorApplication.isCompiling)                         {                             GUILayout.Space(5f);                              Tree();                         }                         else                         {                             if (EditorApplication.isCompiling)                             {                                 GUILayout.Label(_WAIT_COMPILINIG_STR);                             }                         }                     }                 }                 GUILayout.EndVertical();             }         }     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043e\u0434 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u044b\u0439, \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0442\u0443\u0442 &#8212; \u044d\u0442\u043e <strong>Context<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u0442\u0440\u043e\u043a\u0438, \u0432\u0432\u0435\u0434\u0451\u043d\u043d\u043e\u0439 \u0432 \u043f\u043e\u0438\u0441\u043a\u0435 \u0438 <strong>Tree<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<details class=\"spoiler\">\n<summary>\u041c\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 (\u043c\u0435\u0442\u043e\u0434\u044b Context \u0438 Tree)<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private string _context = string.Empty; private bool Context() {     GUILayout.BeginHorizontal(GUI.skin.box);     GUILayout.Label(\"Context search\", GUILayout.Width(100f));     _context = GUILayout.TextField(_context);     GUILayout.EndHorizontal();      if (_context.Length > 0)     {         var components = _vleCatalog.SearchComponentByContext(_context);          _scrollPosition = GUILayout.BeginScrollView(_scrollPosition);         {             TreeComponent(components, false);         }         GUILayout.EndScrollView();     }      return _context.Length > 0; }  private Vector2 _scrollPosition = Vector2.zero;  private GUIStyle _boxComponentStyle; private GUIStyle _tooltipStyle;  private bool _prepared; private const string _COMPONENT_TOOLTIP = \"Please double click for open script\";  private void UpdateGUIStyle() {     if (_prepared) return;      _boxComponentStyle = new GUIStyle(EditorGUIUtility.isProSkin ? GUI.skin.box : GUI.skin.label);     _boxComponentStyle.normal.textColor = Color.white;     _boxComponentStyle.onNormal.textColor = Color.white;      _tooltipStyle = new GUIStyle(GUI.skin.label);     _tooltipStyle.wordWrap = true;      if (!EditorGUIUtility.isProSkin)     {         _tooltipStyle.normal.textColor = Color.white;     }      _prepared = true; }  private void Tree() {     UpdateGUIStyle();      _scrollPosition = GUILayout.BeginScrollView(_scrollPosition);      TreeFolder(((VLECatalog.CatalogFolder)_vleCatalog.Catalog).SubFolders, string.Empty, false);     SaveCatalogState();      GUILayout.EndScrollView(); }  private void TreeFolder(List&lt;VLECatalog.CatalogBase> folders, string path = \"\", bool spaced = true) {     foreach (var catalogComponent in folders)     {         var catalogFolder = (VLECatalog.CatalogFolder)catalogComponent;         var folderPath = path + catalogFolder.Name;          if (!_catalogState.ContainsKey(folderPath))         {             _catalogState.Add(folderPath, false);         }          GUILayout.BeginHorizontal();         {             if (spaced) GUILayout.Space(15f);              GUILayout.BeginVertical();             {                 var guiStyle = EditorStyles.foldout;                 var name = catalogComponent.Name;                 var tooltip = string.Empty;                  if (catalogComponent.Name.Length > 15)                 {                     var stringBuilder = new StringBuilder(name.Substring(0, 12));                      stringBuilder.Append(\"...\");                      name = stringBuilder.ToString();                      tooltip = catalogComponent.Name;                 }                  var content = new GUIContent(EditorGUIUtility.IconContent(\"Folder Icon\"));                  content.text = name;                 content.tooltip = tooltip;                  if (_catalogState[folderPath] = EditorGUILayout.Foldout(_catalogState[folderPath], content, true, guiStyle))                 {                     TreeFolder(catalogFolder.SubFolders, folderPath);                     TreeComponent(catalogFolder.Components);                 }             }             GUILayout.EndVertical();         }         GUILayout.EndHorizontal();     } }  private void TreeComponent(IList&lt;VLECatalog.CatalogBase> components, bool spaced = true) {     foreach (var catalogComponent in components)     {         var component = catalogComponent as VLECatalog.CatalogComponent;         var color = GUI.color;         var componentStyle = new GUIStyle(GUI.skin.box);          GUILayout.BeginHorizontal();         {             if (spaced)             {                 GUILayout.Space(30f);             }              VLELogicEditor.DrawAsDarkSkinImitation(() => GUILayout.BeginVertical(GUI.skin.box), Color.gray);             {                 _boxComponentStyle.normal.textColor = component.ComponentColor;                 _boxComponentStyle.onNormal.textColor = component.ComponentColor;                  var content = new GUIContent(EditorGUIUtility.IconContent(\"blendkey\"));                 content.text = component.Name;                 content.tooltip = _COMPONENT_TOOLTIP;                  Rect labelRect;                  var calcSize = _boxComponentStyle.CalcSize(content);                  if (EditorGUIUtility.isProSkin)                 {                     GUILayout.Box(content, _boxComponentStyle, GUILayout.Width(calcSize.x + 10f));                      labelRect = GUILayoutUtility.GetLastRect();                 }                 else                 {                      VLELogicEditor.DrawAsDarkSkinImitation(() => GUILayout.Box(string.Empty,                                                                                GUILayout.Width(calcSize.x + 10f)),                                                                                VLESetting.DarkLightGrayImitation);                      GUI.Label(labelRect = GUILayoutUtility.GetLastRect(), content, _boxComponentStyle);                 }                  var ev = Event.current;                  if (ev.button == 0 &amp;&amp; ev.clickCount == 2 &amp;&amp; labelRect.Contains(ev.mousePosition))                 {                     VLEditorUtils.OpenScriptByType(component.ComponentType);                 }                  GUILayout.Label(component.Tooltip, _tooltipStyle);             }             GUILayout.EndVertical();              CheckDragComponent(component);         }          GUILayout.EndHorizontal();          GUI.color = color;     } }  private void CheckDragComponent(VLECatalog.CatalogComponent component) {     var ev = Event.current;      if (ev.type == EventType.MouseDrag &amp;&amp; GUILayoutUtility.GetLastRect().Contains(ev.mousePosition))     {         DragAndDrop.PrepareStartDrag();          DragAndDrop.objectReferences = new UnityEngine.Object[0];         DragAndDrop.paths = new string[0];         DragAndDrop.SetGenericData(\"VLEDragData\", component);         DragAndDrop.StartDrag(\"VLEDragData\");          ev.Use();     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u043f\u043e \u043a\u043e\u0434\u0443, \u0437\u0434\u0435\u0441\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u044f \u043c\u0435\u0442\u043e\u0434\u0430 <strong>TreeFolder<\/strong> \u0434\u043b\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0432\u0441\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445 \u0438 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445. \u0422\u0430\u043a\u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 <strong>Drag&amp;Drop<\/strong> \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432 \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u0443\u0442\u0435\u043c \u043f\u0435\u0440\u0435\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0414\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u043e\u043c \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u0441\u0435\u0441\u0441\u0438\u044f\u043c\u0438, \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043b\u0435\u0436\u0438\u0442 \u0432\u043d\u0435 \u043f\u0430\u043f\u043a\u0438 <strong>Assets<\/strong>.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public partial class VLECatalogWindow     {         [Serializable]         private class CatalogFolderState         {             [Serializable]             public class Data             {                 public string Path { get; private set; }                 public bool State { get; private set; }                  public Data(string path, bool state)                 {                     Path = path;                     State = state;                 }             }              public readonly List&lt;Data> Info = new List&lt;Data>();         }          private IDictionary&lt;string, bool> _catalogState;          private void LoadCatalogState()         {             _catalogState = new Dictionary&lt;string, bool>();              var catalogFolderState = Serialization.Deserialize(Path.Combine(Directory.GetParent(Application.dataPath).FullName, \"_uViLEd Setting\"), \"CatalogFolderState.setting\") as CatalogFolderState;              if (catalogFolderState == null) return;                          catalogFolderState.Info.ForEach(folder => _catalogState.Add(folder.Path, folder.State));         }          private void SaveCatalogState()         {             var catalogFolderState = new CatalogFolderState();              foreach (var info in _catalogState)             {                 catalogFolderState.Info.Add(new CatalogFolderState.Data(info.Key, info.Value));             }              Serialization.Serialize(catalogFolderState, Path.Combine(Directory.GetParent(Application.dataPath).FullName, \"_uViLEd Setting\"), \"CatalogFolderState.setting\");         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0439 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438<\/em>.<\/p>\n<h2>\u041f\u043e\u0438\u0441\u043a<\/h2>\n<p>\u0412 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u043e\u0431\u044a\u0435\u043c \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u043c. \u041e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442\u044c \u043f\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044f \u0441\u0434\u0435\u043b\u0430\u043b \u043e\u043a\u043d\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u0441 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u043c \u043a \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"581\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/da8\/ef2\/93f\/da8ef293fd19bfffe6718687f206393b.png\" data-width=\"320\"\/><figcaption><\/figcaption><\/figure>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434 \u043e\u043a\u043d\u0430 \u043f\u043e\u0438\u0441\u043a\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public class SearchComponentWindow : VLEWindowEditor     {         private string _searchingName = string.Empty;          private Vector2 _scrollSearchResultPosition = Vector2.zero;                  private IList&lt;ILogicWidget> _currentVLEWidgets;         private IList&lt;IWidgetGroup> _currentGroups;         private IList&lt;IWidgetGroup> _logicGroups;         private IList&lt;ILogicWidget> _vleWidgets;          private VLELogicEditor.ILogic _currentLogicDrawer;         private string[] _tabs = new string[] { \"Components\", \"Groups\" };         private int _currentTabs = 0;          public void Initialization(IList&lt;ILogicWidget> currentVLEWidgets, IList&lt;IWidgetGroup> currentGroups, VLELogicEditor.ILogic currentLogicDrawer)         {             _searchingName = string.Empty;             _currentVLEWidgets = currentVLEWidgets;             _vleWidgets = new List&lt;ILogicWidget>(currentVLEWidgets);             _currentGroups = currentGroups;             _logicGroups = new List&lt;IWidgetGroup>(currentGroups);             _currentLogicDrawer = currentLogicDrawer;         }          void OnGUI()         {             GUILayout.Space(5f);             GUILayout.BeginHorizontal(GUI.skin.box);             {                 GUILayout.Label(\"Context search\", GUILayout.Width(100f));                 _searchingName = GUILayout.TextField(_searchingName);             }             GUILayout.EndHorizontal();              _scrollSearchResultPosition = GUILayout.BeginScrollView(_scrollSearchResultPosition, GUIStyle.none, GUI.skin.verticalScrollbar);              switch (_currentTabs = GUILayout.Toolbar(_currentTabs, _tabs))             {                 case 0:                     {                         if (_currentVLEWidgets.Count != _vleWidgets.Count)                         {                             _vleWidgets.Clear();                             (_vleWidgets as List&lt;ILogicWidget>)?.AddRange(_currentVLEWidgets);                         }                          for (var i = 0; i &lt; _vleWidgets.Count; i++)                         {                             var component = _vleWidgets[i];                              if (component != null)                             {                                 var subString = component.Name.Substring(0, Mathf.Clamp(_searchingName.Length, 0, component.Name.Length)).ToLower();                                  if (subString == _searchingName.ToLower() || _searchingName == String.Empty)                                 {                                     var guiColor = GUI.color;                                      GUI.color = component.WidgetColor;                                      if (GUILayout.Button(component.Name))                                     {                                         component.Select(true, false);                                          _currentLogicDrawer.CenterToComponent(component);                                     }                                      GUI.color = guiColor;                                 }                             }                         }                     }                     break;                 case 1:                     {                         if (_currentGroups.Count != _logicGroups.Count)                         {                             _logicGroups.Clear();                              (_vleWidgets as List&lt;IWidgetGroup>)?.AddRange(_currentGroups);                         }                          for (var i = 0; i &lt; _logicGroups.Count; i++)                         {                             var group = _logicGroups[i];                              if (group != null)                             {                                 var subString = group.Name.Substring(0, Mathf.Clamp(_searchingName.Length, 0, group.Name.Length)).ToLower();                                  if (subString == _searchingName.ToLower() || _searchingName == String.Empty)                                 {                                     var guiColor = GUI.color;                                      GUI.color = group.GroupColor;                                      if (GUILayout.Button(group.Name))                                     {                                         var component = group.Widgets[0];                                          _currentLogicDrawer.CenterToComponent(component);                                     }                                      GUI.color = guiColor;                                 }                             }                         }                     }                     break;             }              GUILayout.EndScrollView();         }          private void OnDisable()         {             _logicGroups.Clear();             _logicGroups = null;              _vleWidgets.Clear();             _vleWidgets = null;              _currentVLEWidgets = null;         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e, \u0437\u0434\u0435\u0441\u044c \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0438 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u043d\u044b\u0439 \u043f\u043e\u0438\u0441\u043a \u043f\u043e \u0438\u043c\u0435\u043d\u0438. \u041f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0446\u0435\u043d\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0451\u043c.<\/p>\n<h2>\u041e\u0442\u043b\u0430\u0434\u043a\u0430<\/h2>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438, \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u043a\u0430\u043a \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0440\u0435\u0434\u0443\u0441\u043c\u043e\u0442\u0440\u0435\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u043e\u0442\u043b\u0430\u0434\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438).<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u043b\u0435\u0434\u0438\u0442\u044c \u0446\u0435\u043f\u043e\u0447\u043a\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432\u0441\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0442\u044c \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u044b\u0439 \u0432\u044b\u0437\u043e\u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 (\u0432\u044b\u0437\u043e\u0432 \u0441\u0432\u044f\u0437\u0435\u0439).<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043e\u0442\u043b\u0430\u0434\u043a\u0438:<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"\/img\/image-loader.svg\" height=\"606\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/5c3\/c82\/f42\/5c3c82f4246413af98ae889dc1213473.png\" data-width=\"912\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0434\u0435\u0441\u044c \u0437\u0435\u043b\u0435\u043d\u044b\u043c \u043e\u0442\u043c\u0435\u0447\u0430\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b, \u0447\u044c\u044f \u043b\u043e\u0433\u0438\u043a\u0430 \u0431\u044b\u043b\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430, \u0430 \u0441\u0438\u043d\u0438\u043c, \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0438\u043b\u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0431\u044b\u043b\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0430.<\/p>\n<p>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0436\u0438\u043c\u0430 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">#if UNITY_EDITOR  namespace uViLEd.Editor {     public class VLEDebug     {         public delegate void TracertStackChanged(TracertData tracertData);         public delegate void NextStep();          public static event TracertStackChanged OnTracertStackChanged;         public static event NextStep OnNextStep;          public class TracertData         {             public string LogicId { get; private set; }             public string Link { get; private set; }             public string Data { get; private set; }              public TracertData(string logicId, string link, string data)             {                 LogicId = logicId;                 Link = link;                 Data = data;             }         }          public static bool IsBreak { get; private set; } = false;          public static void TRACERT(string logicId, string link) => OnTracertStackChanged?.Invoke(new TracertData(logicId, link, string.Empty));                 public static void TRACERT(string logicId, string link, string data) => OnTracertStackChanged?.Invoke(new TracertData(logicId, link, data));                 public static void Break() => IsBreak = true;                 public static void Next() => OnNextStep?.Invoke();                 public static void Play()         {             IsBreak = false;              OnNextStep?.Invoke();         }          public static void Clear()         {                         if (OnNextStep != null)             {                 foreach (var eventHandler in OnNextStep.GetInvocationList())                 {                     OnNextStep -= (NextStep)eventHandler;                 }             }         }                 }     } #endif<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0427\u0442\u043e \u0436\u0435 \u0434\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441? \u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432 \u043d\u0435\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b, \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0438\u0445 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0447\u0430\u0441\u0442\u044f\u0445 \u043a\u043e\u0434\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u044f\u0434\u0440\u0430. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u044d\u0442\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435. \u041a\u043b\u0430\u0441\u0441 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0434\u0432\u0430 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u044f:<\/p>\n<ol>\n<li>\n<p>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u0442\u0435\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u0432\u044f\u0437\u0435\u0439, \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0434\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435, \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0435\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442).<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0448\u0430\u0433\u0430 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438, \u0434\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0435 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430:<\/p>\n<ol>\n<li>\n<p><strong>TRACERT<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0434\u043b\u044f \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0441\u0432\u044f\u0437\u0438 (\u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0432\u0438\u0434\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043a\u043b\u0430\u0441\u0441\u0430, \u0433\u0434\u0435 \u0437\u0430\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438, \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0441\u0432\u044f\u0437\u0438 \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443).<\/p>\n<\/li>\n<li>\n<p><strong>Break<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 (\u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 \u043f\u0430\u0443\u0437\u0443).<\/p>\n<\/li>\n<li>\n<p><strong>Next<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0434\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u043e \u0446\u0435\u043f\u043e\u0447\u043a\u0435 \u0441\u0432\u044f\u0437\u0438 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Play<\/strong> \u2013 \u043c\u0435\u0442\u043e\u0434, \u0441\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u043f\u0430\u0443\u0437\u0443 \u0441 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0442\u0430\u043a, \u043a\u0430\u043a \u044d\u0442\u043e \u0432\u0441\u0451 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u0438 \u0441 \u044f\u0434\u0440\u043e\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u043c \u043b\u043e\u0433\u0438\u043a\u0438. \u0414\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0432\u044b\u0437\u043e\u0432\u0443 \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438, \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u0434 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Core {     public class OUTPUT_POINT&lt;T>     {         private List&lt;Action&lt;T>> _linkedInputPoints = new List&lt;Action&lt;T>>();          private Action&lt;T> ParsingActionEmpty(Action action, string logicId, string linkId)         {             Action&lt;T> parsedAction = (value) =>             {                 Editor.VLEDebug.TRACERT(logicId, linkId, value.ToString());                  action();             };              return parsedAction;         }          private Action&lt;T> ParsingActionObject(Action&lt;object> action, string logicId, string linkId)         {             Action&lt;T> parsedAction = (value) =>             {                 Editor.VLEDebug.TRACERT(logicId, linkId, value.ToString());                  action(value);             };              return parsedAction;         }          private Action&lt;T> ParsingActionT(Action&lt;T> action, string logicId, string linkId)         {             Action&lt;T> parsedAction = (value) =>             {                 Editor.VLEDebug.TRACERT(logicId, linkId, value.ToString());                  action(value);             };              return parsedAction;         }          public void Execute(T param)         {              if (Editor.VLEDebug.IsBreak)             {                 if (_storedParam.Count == 0)                 {                     Editor.VLEDebug.OnNextStep += WaitNextStep;                 }                  _storedParam.Enqueue(param);             }             else             {                 foreach (var handler in _linkedInputPoints)                 {                     handler(param);                 }             }         }          private Queue&lt;T> _storedParam = new Queue&lt;T>();          private void WaitNextStep()         {             if (Editor.VLEDebug.IsBreak)             {                 var param = _storedParam.Dequeue();                  if (_storedParam.Count == 0)                 {                     Editor.VLEDebug.OnNextStep -= WaitNextStep;                 }                  foreach (var handler in _linkedInputPoints)                 {                     handler(param);                 }             }             else             {                 while (_storedParam.Count > 0)                 {                     var param = _storedParam.Dequeue();                      foreach (var handler in _linkedInputPoints)                     {                         handler(param);                     }                 }                  Editor.VLEDebug.OnNextStep -= WaitNextStep;             }         }     }      public class OUTPUT_POINT     {         private List&lt;Action> _linkedInputPoints = new List&lt;Action>();          public void Execute()         {             if (Editor.VLEDebug.IsBreak)             {                 if (_callCount == 0)                 {                     Editor.VLEDebug.OnNextStep += WaitNextStep;                 }                  _callCount++;             }             else             {                 foreach (var handler in _linkedInputPoints)                 {                     handler();                 }             }         }         private int _callCount = 0;          private void WaitNextStep()         {             if (Editor.VLEDebug.IsBreak)             {                 _callCount--;                  if (_callCount == 0)                 {                     Editor.VLEDebug.OnNextStep -= WaitNextStep;                 }                  foreach (var handler in _linkedInputPoints)                 {                     handler();                 }             }             else             {                 _callCount = 0;                 Editor.VLEDebug.OnNextStep -= WaitNextStep;                  foreach (var handler in _linkedInputPoints)                 {                     handler();                 }             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0430 \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0442\u0443\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435:<\/p>\n<ol>\n<li>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c Parsing, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442 \u0434\u0435\u043b\u0435\u0433\u0430\u0442 \u0432 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u0441 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043a \u043d\u0435\u043c\u0443 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <strong>Editor.VLEDebug.TRACERT<\/strong><\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u043e\u0448\u0430\u0433\u043e\u0432\u043e\u0439 \u043e\u0442\u043b\u0430\u0434\u043a\u0438. \u0412 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 \u0441\u0432\u044f\u0437\u0438 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043b\u043e\u0433\u0438\u043a\u0430 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 \u043f\u0430\u0443\u0437\u0435, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u043d\u0435\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u0440\u043e\u0431\u0440\u043e\u0441\u0430 \u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u0443\u044e \u0442\u043e\u0447\u043a\u0443 \u043d\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442. \u0414\u0430\u043b\u0435\u0435 \u0442\u043e\u0447\u043a\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 <strong>Editor.VLEDebug.OnNextStep<\/strong>, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0443\u0436\u0435 \u0432\u044b\u0437\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0445 \u0442\u043e\u0447\u0435\u043a. \u0414\u0430\u043d\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u043e\u0447\u0435\u043a, \u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u043a\u0430\u0437\u0430\u043d \u0442\u0438\u043f \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432. \u0414\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u043e\u0432 \u0432\u044b\u0437\u043e\u0432\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u044f, \u043a\u043e\u0433\u0434\u0430 \u0432 \u043a\u043e\u0434\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432\u044b\u0437\u043e\u0432 \u0441\u0432\u044f\u0437\u0435\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u0446\u0438\u043a\u043b\u0435.<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0440\u0435\u0436\u0438\u043c\u0430 \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>VLELogicEditor<\/strong> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f <strong>OnTracertStackChanged<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void OnTracertDataChanged(VLEDebug.TracertData tracertData) {     if (tracertData.LogicId != VLECommon.CurrentLogic.Id)     {         if (VLEDebug.IsBreak)         {             var logic = VLECommon.CurrentLogicController.SceneLogicList.Find(item => item.Id == tracertData.LogicId);              if (logic == null)             {                 return;             }              LoadLogic(VLECommon.CurrentLogicController.SceneLogicList.IndexOf(logic));         }         else         {             return;         }     }      var link = _logicLinks.Find((value) =>     {         if (value.Id == tracertData.Link)         {             return true;         }         else         {             return false;         }     });      if (link != null)     {         link.MakeTracert(true, tracertData.Data);     }     else     {         Debug.LogWarning($\"[uViLEd]: failed tracert link [{tracertData.Link}], link not exist\");     }      Repaint(); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u0448\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430, \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0442\u043b\u0430\u0436\u0438\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0412\u0441\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043b\u043e\u0433\u0438\u043a\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 (\u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0438\u0445 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435).<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043d\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <strong>ViewInEditorAttribute<\/strong>.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0445 \u043f\u043e\u043b\u0435\u0439 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <strong>ViewInDebugModeAttribute<\/strong>.<\/p>\n<\/li>\n<\/ol>\n<p>\u041a\u0430\u043a \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0435\u0439 \u043a\u043b\u0430\u0441\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f\u043c (\u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u043f\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u0430\u043c):<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public static IDictionary&lt;FieldInfo, bool> GetParameters(Type instanceType) {     var returnedValue = new Dictionary&lt;FieldInfo, bool>();     var publicFieldsInfo = instanceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);      for (var i = 0; i &lt; publicFieldsInfo.Length; i++)     {         var fieldInfo = publicFieldsInfo[i];          if (fieldInfo.FieldType.IsGenericType &amp;&amp; fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(VARIABLE_LINK&lt;>))         {             var hideInEditor = fieldInfo.GetCustomAttributes(typeof(HideInEditorAttribute), true);              if (hideInEditor.Length == 0)             {                 returnedValue.Add(fieldInfo, false);             }         }         else         {             if ((fieldInfo.FieldType.IsGenericType &amp;&amp;                 (fieldInfo.FieldType.GetGenericTypeDefinition() != typeof(OUTPUT_POINT&lt;>)) &amp;&amp;                 (fieldInfo.FieldType.GetGenericTypeDefinition() != typeof(INPUT_POINT&lt;>)))                 ||                (!fieldInfo.FieldType.IsGenericType &amp;&amp;                  fieldInfo.FieldType != typeof(OUTPUT_POINT) &amp;&amp;                  fieldInfo.FieldType != typeof(INPUT_POINT)))             {                 var viewInEditor = fieldInfo.GetCustomAttributes(typeof(ViewInEditorAttribute), true);                  if (viewInEditor.Length > 0)                 {                     returnedValue.Add(fieldInfo, false);                 }             }         }     }       var allFieldsInfo = instanceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);      for (var i = 0; i &lt; allFieldsInfo.Length; i++)     {         var fieldInfo = allFieldsInfo[i];          if ((fieldInfo.FieldType.IsGenericType &amp;&amp;            (fieldInfo.FieldType.GetGenericTypeDefinition() != typeof(OUTPUT_POINT&lt;>)) &amp;&amp;            (fieldInfo.FieldType.GetGenericTypeDefinition() != typeof(INPUT_POINT&lt;>)))            ||           (!fieldInfo.FieldType.IsGenericType &amp;&amp;             fieldInfo.FieldType != typeof(OUTPUT_POINT) &amp;&amp;             fieldInfo.FieldType != typeof(INPUT_POINT)))         {             var viewInDebugMode = fieldInfo.GetCustomAttributes(typeof(ViewInDebugModeAttribute), true);              if (viewInDebugMode.Length > 0)             {                 returnedValue.Add(fieldInfo, true);             }         }     }      return returnedValue; }<\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/h2>\n<p>\u041a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043b\u043e\u0433\u0438\u043a\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u0441\u0445\u043e\u0436\u0435\u043c\u0443 \u0441 \u0442\u0430\u043a\u043e\u0432\u044b\u043c \u0432 <strong>Unity3D<\/strong>: \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442 <strong>VLECustomComponentDrawer<\/strong> \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c \u0442\u0438\u043f\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Components.Editor {     [VLECustomComponentDrawer(typeof(VariableColor))]     public class VariableColorCustomDrawer : VLEVariable     {         public class VariableColorValueWidget : VariableValueWidget         {                         public VariableColorValueWidget(VariableValueData valueData, IWidgetContainer rootContainer) : base(valueData, rootContainer) { }              public override void UpdateView() { }             public override void Draw() => EditorGUI.DrawRect(valueAreaRect, (Color)valueData.Value);                     }          public VariableColorCustomDrawer(Core.LogicStorage.ComponentsStorage.ComponentData componentStorage) : base(componentStorage) { }          protected override void PrepareChildWidget()         {             ReplaceWidget&lt;VariableValueWidget, VariableColorValueWidget>();              base.PrepareChildWidget();         }          public override void UpdateParameterValues()         {             var propertyInfo = VLEditorUtils.GetVariable(InstanceType);              valueData.Value = propertyInfo.GetValue(Instance, null);         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0431\u043e\u0440\u043a\u0430\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445 (\u0438\u0441\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u0432\u0438\u0436\u043a\u0430 <strong>Unity3d<\/strong>) \u0438 \u0432\u0441\u0435 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b \u043a\u044d\u0448\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0441\u043b\u043e\u0432\u0430\u0440\u0435, \u0433\u0434\u0435 \u043a\u043b\u044e\u0447\u043e\u043c \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0442\u0438\u043f \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void LoadEditorRuntimeAssembly() {     var allAssembliesDomain = AppDomain.CurrentDomain.GetAssemblies();      _customDrawerTypes.Clear();      foreach (var assembly in allAssembliesDomain)     {         if (assembly.FullName.Contains(\"System\") ||             assembly.FullName.Contains(\"UnityEditor\") ||             assembly.FullName.Contains(\"UnityEngine\"))         {             continue;         }         else         {             var vleBaseComponents = assembly.GetTypes();              foreach (var vseBaseComponent in vleBaseComponents)             {                 var attributes = vseBaseComponent.GetCustomAttributes(typeof(VLECustomComponentDrawerAttribute), true);                  if (attributes.Length > 0)                 {                     foreach (var attribute in attributes)                     {                         var customDrawer = (VLECustomComponentDrawerAttribute)attribute;                          _customDrawerTypes.Add(customDrawer.ComponentType, vseBaseComponent);                     }                 }             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e, \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u043e\u0432 \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043d\u0430 \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u043e \u0442\u0438\u043f\u0443 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private Type GetCustomDrawerType(Type componentType) {     if (_customDrawerTypes.ContainsKey(componentType))     {         return _customDrawerTypes[componentType];     }     else     {         foreach (var logicComponentType in _customDrawerTypes.Keys)         {             if (logicComponentType.IsAssignableFrom(componentType))             {                 return _customDrawerTypes[logicComponentType];             }         }     }      return null; }  ILogicWidget logicWidget;  var customDrawerType = GetCustomDrawerType(componentType);  if (customDrawerType != null) {     logicWidget = Activator.CreateInstance(customDrawerType, new object[] { componentStorage }) as ILogicWidget; } else {     if (typeof(Core.Variable).IsAssignableFrom(componentType))     {         logicWidget = new VLEVariable(componentStorage);     }     else     {         logicWidget = new VLEComponent(componentStorage);     } } <\/code><\/pre>\n<\/div>\n<\/details>\n<h2>\u041c\u0430\u0445\u0438\u043d\u0430\u0446\u0438\u0438<\/h2>\n<h3>\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f<\/h3>\n<p>\u041e\u0431\u043b\u0430\u0441\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 <strong>Handles<\/strong> \u0438\u0437 \u0441\u043e\u0441\u0442\u0430\u0432\u0430 <strong>Unity3D<\/strong>.<\/p>\n<pre><code class=\"cs\">Handles.DrawSolidRectangleWithOutline(_multiSelectRect, _faceSelectionColor, Color.black);<\/code><\/pre>\n<p>\u0420\u0430\u0441\u0447\u0435\u0442 <strong>_multiSelectRect<\/strong> \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0438 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430 \u043c\u044b\u0448\u0438. \u041f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u043b\u0435\u0432\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438 \u043c\u044b\u0448\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code class=\"cs\">if (!_multiSelectMoveMode &amp;&amp; logicAreaRect.Contains(ev.mousePosition)) {     _multiSelectMode = true;     _multiSelectRect.position = GetLogicAreaPosition(ev.mousePosition);     _multiSelectRect.width = 0f;     _multiSelectRect.height = 0f;      ev.Use(); }<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043f\u0440\u0438 \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0438 \u043c\u044b\u0448\u0438 \u043f\u0435\u0440\u0435\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0448\u0438\u0440\u0438\u043d\u044b \u0438 \u0432\u044b\u0441\u043e\u0442\u044b \u043e\u0431\u043b\u0430\u0441\u0442\u0438:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">if (_multiSelectMode) {     _multiSelectRect.width = (ev.mousePosition.x + logicScrollPosition.x - logicRealRect.position.x) - _multiSelectRect.position.x;     _multiSelectRect.height = (ev.mousePosition.y + logicScrollPosition.y - logicRealRect.position.y) - _multiSelectRect.position.y;      for (var i = 0; i &lt; _logicWidgets.Count; i++)     {         var component = _logicWidgets[i];          if (_multiSelectRect.Overlaps(component.Area, true))         {             component.Select(true);         }         else         {             component.Select(false);         }     }      if (!logicAreaRect.Contains(ev.mousePosition))     {         if (ev.mousePosition.x >= logicAreaRect.xMax)         {             logicScrollPosition.x += (0.1f) * (ev.mousePosition.x - logicAreaRect.xMax);         }         else if (ev.mousePosition.x &lt;= logicAreaRect.xMin)         {             logicScrollPosition.x += (0.1f) * (ev.mousePosition.x - logicAreaRect.xMin);         }          if (ev.mousePosition.y >= logicAreaRect.yMax)         {             logicScrollPosition.y += (0.1f) * (ev.mousePosition.y - logicAreaRect.yMax);         }         else if (ev.mousePosition.y &lt;= logicAreaRect.yMin)         {             logicScrollPosition.y += (0.1f) * (ev.mousePosition.y - logicAreaRect.yMin);         }     }      ev.Use(); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c \u0441\u0442\u043e\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043a\u0443\u0440\u0441\u043e\u0440 \u043c\u044b\u0448\u0438 \u0432\u044b\u0445\u043e\u0434\u0438\u0442 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438, \u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0441\u043a\u0440\u043e\u043b\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<h3>\u0418\u043c\u0438\u0442\u0438\u0440\u0443\u0435\u043c \u0442\u0435\u043c\u043d\u044b\u0439 \u0441\u043a\u0438\u043d<\/h3>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 <strong>Unity3d<\/strong> \u0432 \u0432\u0435\u0440\u0441\u0438\u044f\u0445 \u0434\u043e <strong>2019<\/strong> \u0433\u043e\u0434\u0430 \u0440\u0435\u0436\u0438\u043c \u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u043a\u0438\u043d\u0430 \u044f\u0432\u043b\u044f\u043b\u0441\u044f \u043f\u0440\u0435\u043c\u0438\u0443\u043c \u0444\u0438\u0447\u0435\u0439, \u0442\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0430\u0434\u0435\u043a\u0432\u0430\u0442\u043d\u043e\u0433\u043e \u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0441\u044f \u0431\u044b\u043b\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u0438\u043c\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u0442\u0435\u043c\u043d\u044b\u0439 \u0441\u043a\u0438\u043d \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0431\u044b\u043b\u0430 \u0437\u0430\u0432\u0435\u0434\u0435\u043d \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043c\u0435\u0442\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u043b \u043c\u0435\u043d\u044f\u0442\u044c \u0446\u0432\u0435\u0442 \u0434\u043b\u044f \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 <strong>UI<\/strong> \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0432\u043a\u043b\u044e\u0447\u0435\u043d \u0438\u043b\u0438 \u043d\u0435\u0442 \u0442\u0435\u043c\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c.<\/p>\n<pre><code class=\"cs\">public static void DrawAsDarkSkinImitation(Action draw, Color color) {     if (EditorGUIUtility.isProSkin)     {         draw();     }     else     {         var guiColor = GUI.color;         GUI.color = color;         draw();         GUI.color = guiColor;     } }<\/code><\/pre>\n<p>\u0414\u0430\u043b\u0435\u0435 \u044d\u0442\u043e\u0442 \u043c\u0435\u0442\u043e\u0434 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0441\u044f \u0434\u043b\u044f \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u0432\u0441\u0435\u0445 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0438 \u0438\u043c\u0438\u0442\u0430\u0446\u0438\u0438.<\/p>\n<pre><code class=\"cs\">VLELogicEditor.DrawAsDarkSkinImitation(() => GUILayout.Box(string.Empty,                                                            GUILayout.Width(calcSize.x + 10f)),                                                            VLESetting.DarkLightGrayImitation); <\/code><\/pre>\n<h3>\u041c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/h3>\n<p>\u041f\u0440\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438, \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044f \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u043b\u0441\u044f, \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u042f \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0440\u0430\u0437\u043d\u044b\u0435 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u044b, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <strong>GL.matrix<\/strong>, \u043d\u043e \u043c\u0435\u043d\u044f \u0432\u0441\u0435 \u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043b\u043e, \u043b\u0438\u0431\u043e \u043f\u043e \u0447\u0430\u0441\u0442\u0438 \u0432\u0438\u0437\u0443\u0430\u043b\u0430, \u043b\u0438\u0431\u043e \u043f\u043e \u0447\u0430\u0441\u0442\u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0441 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043b \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0435, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u043d\u043e\u0435, \u043d\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u0435\u0440\u0442\u043e\u043a \u0434\u043b\u044f <strong>Rect<\/strong>, \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0448\u0440\u0438\u0444\u0442\u0430:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public static class VLEExtension     {         public abstract class VLEVirtualBase         {             protected float currentPixelSize = float.MinValue;         }         public class VLEVirtualRect : VLEVirtualBase         {             private Rect _sourceRect;             private Rect _currentRect;              public VLEVirtualRect(float x, float y, float width, float height) : base()             {                 _sourceRect = new Rect(x, y, width, height);                 _currentRect = _sourceRect;             }              public Rect GetRect(float pixelSize = 1f)             {                 if (pixelSize != currentPixelSize)                 {                     currentPixelSize = pixelSize;                      var x = Mathf.Round(_sourceRect.x * pixelSize);                     var y = Mathf.Round(_sourceRect.y * pixelSize);                     var width = Mathf.Round(_sourceRect.width * pixelSize);                     var height = Mathf.Round(_sourceRect.height * pixelSize);                      _currentRect = new Rect(x, y, width, height);                 }                  return _currentRect;             }              public void SetPosition(Vector2 position, float pixelSize = 1f)             {                 _sourceRect.x = Mathf.Round(position.x * 1f \/ pixelSize);                 _sourceRect.y = Mathf.Round(position.y * 1f \/ pixelSize);                  currentPixelSize = 0f;             }               public void SetX(float x, float pixelSize = 1f)             {                 _sourceRect.x = Mathf.Round(x * 1f \/ pixelSize);                  currentPixelSize = 0f;             }              public void SetY(float y, float pixelSize = 1f)             {                 _sourceRect.y = Mathf.Round(y * 1f \/ pixelSize);                  currentPixelSize = 0f;             }              public void SetWidth(float width, float pixelSize = 1f)             {                 _sourceRect.width = Mathf.Round(width * 1f \/ pixelSize);                  currentPixelSize = 0f;             }              public void SetHeight(float height, float pixelSize = 1f)             {                 _sourceRect.height = Mathf.Round(height * 1f \/ pixelSize);                  currentPixelSize = 0f;             }         }          public class VLEVirtualPosition : VLEVirtualBase         {             private Vector2 _sourcePosition;             private Vector2 _currentPosition;              public VLEVirtualPosition(float x, float y) : base()             {                 _sourcePosition = new Vector2(x, y);                 _currentPosition = _sourcePosition;             }              public Vector2 GetPosition(float pixelSize)             {                 if (pixelSize != currentPixelSize)                 {                     currentPixelSize = pixelSize;                      _currentPosition = new Vector2(Mathf.Round(_sourcePosition.x * pixelSize), Mathf.Round(_sourcePosition.y * pixelSize));                 }                  return _currentPosition;             }              public void SetPosition(Vector2 position, float pixelSize)             {                 _sourcePosition.x = Mathf.Round(position.x * 1f \/ pixelSize);                 _sourcePosition.y = Mathf.Round(position.y * 1f \/ pixelSize);                  if (currentPixelSize == pixelSize)                 {                     _currentPosition = position;                 }             }         }          public class VLEVirualFontSize : VLEVirtualBase         {             private int _sourceFontSize;             private int _currentFontSize;              public VLEVirualFontSize(int fontSize) : base() => _sourceFontSize = _currentFontSize = fontSize;                          public int GetFontSize(float pixelSize)             {                 if (pixelSize != currentPixelSize)                 {                     currentPixelSize = pixelSize;                      _currentFontSize = (int)Mathf.Floor((float)_sourceFontSize * pixelSize);                 }                  return _currentFontSize;             }         }            } } <\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u0435\u0441\u044c \u043a\u043e\u0434 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u0442\u0438 \u0442\u0440\u0438 \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f. <\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u0430\u0441\u0441\u0430 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public partial class VLEComponent {     public class StateWidget : ChildWidget     {         protected GUIStyle stateStyle;         protected IComponentWidget component;          protected VLEExtension.VLEVirualFontSize virtualFontSize = new VLEExtension.VLEVirualFontSize(10);          public StateWidget(IComponentWidget component)         {             this.component = component;              widgetVirtualRect = new VLEExtension.VLEVirtualRect(210f, 20f, 30f, 20f);         }          public override void RegisterStyle()         {             if (stateStyle == null)             {                 stateStyle = new GUIStyle(GUI.skin.label);                 stateStyle.fontStyle = FontStyle.Normal;                 stateStyle.clipping = TextClipping.Clip;                 stateStyle.normal.textColor = Color.gray;             }         }          public override void Draw()         {             if (component.IsCanMinimize &amp;&amp; component.IsMinimized)             {                 stateStyle.fontSize = virtualFontSize.GetFontSize(VLECommon.CurrentEditorScale);                  var rect = Area; rect.y = Mathf.Clamp(rect.y, 15f, 20f);                  GUI.Label(rect, \"min\", stateStyle);             }         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0438\u0442\u043e\u0433, \u0441\u0430\u043c\u043e \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u043c\u0435\u0440\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0438\u043a\u0441\u0435\u043b\u044f, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <strong>VLECommon.CurrentEditorScale<\/strong>.<\/p>\n<h3>\u0422\u0430\u0439\u043c\u0435\u0440<\/h3>\n<p>\u0422\u0430\u0439\u043c\u0435\u0440 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0434\u043e \u0430\u0432\u0442\u043e\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043a\u043e\u0440\u043e\u0443\u0442\u0438\u043d \u043d\u0435 \u0431\u044b\u043b\u043e \u0432 \u0435\u0449\u0435 \u0432 \u0434\u043e\u0441\u0442\u0443\u043f\u0435 \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u043e\u0448\u0430\u043c\u0430\u043d\u0438\u0442\u044c. \u0412 \u0438\u0442\u043e\u0433\u0435 \u0440\u043e\u0434\u0438\u043b\u0441\u044f \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">namespace uViLEd.Editor {     public class VLETime     {         public static float Time => UnityEngine.Time.realtimeSinceStartup;         public static float DeltaTime => _deltaTime;          private static float _previousTime = 0f;         private static float _deltaTime = 0f;          public static void Start() => _previousTime = Time;                 public static void Update()         {             _deltaTime = Time - _previousTime;             _previousTime = Time;         }     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0421\u0435\u0442\u043a\u0430<\/h3>\n<p>\u0412\u0441\u0435 \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u0437\u043d\u0430\u044e\u0442, \u0447\u0442\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430\u0445 (<strong>Bolt<\/strong>, <strong>Blueprint<\/strong>, <strong>Shader Grpaph<\/strong>) \u043d\u0430 \u0437\u0430\u0434\u043d\u0438\u043a\u0435 \u0440\u0438\u0441\u0443\u0435\u0442\u0441\u044f \u043a\u0440\u0430\u0441\u0438\u0432\u0430\u044f \u0441\u0435\u0442\u043e\u0447\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0435\u0449\u0435 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0441\u043a\u0435\u0439\u043b\u0438\u043d\u0433\u0435. \u041c\u043d\u0435 \u0442\u043e\u0436\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0442\u0430\u043a\u0443\u044e \u0443 \u0441\u0435\u0431\u044f. \u041e\u043f\u044f\u0442\u044c \u0436\u0435 \u044f \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0438 \u0432 \u0438\u0442\u043e\u0433\u0435 \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0438\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u044d\u0442\u043e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u043e\u0435 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435.<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">public static void DrawGrid(Rect viewArea, Vector3 offset, float gridSizeX, float gridSizeY, Color color, Color accentColor) {     var storeColor = Handles.color;      if (gridSizeX == 0 || gridSizeY == 0) return;      var startXLineCount = ((int)(offset.x \/ gridSizeX)) + 1;     var startYLineCount = ((int)(offset.y \/ gridSizeY)) + 1;      var x = startXLineCount * gridSizeX;     var y = startYLineCount * gridSizeY;      var counter = startXLineCount;      while (x &lt;= offset.x + viewArea.width)     {         var from = new Vector2(x, offset.y);         var to = new Vector2(x, offset.y + viewArea.height);          x += gridSizeX;          if ((counter > 0) &amp;&amp; (counter % 10 == 0))         {             Handles.color = accentColor;         }         else         {             Handles.color = color;         }          Handles.DrawLine(from, to);          counter++;     }      counter = startYLineCount;      while (y &lt;= offset.y + viewArea.height)     {         var from = new Vector2(offset.x, y);         var to = new Vector2(offset.x + viewArea.width, y);          y += gridSizeY;          if ((counter > 0) &amp;&amp; (counter % 10 == 0))         {             Handles.color = accentColor;         }         else         {             Handles.color = color;         }          Handles.DrawLine(from, to);          counter++;     }      Handles.color = storeColor; }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0444\u0438\u0448\u043a\u0430 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0442\u0435 \u043b\u0438\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u0432\u0438\u0434\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d\u0438. \u041f\u0440\u0438\u043c\u0435\u043d\u0438\u0432 \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0439 \u043f\u043e\u0434\u0445\u043e\u0434, \u044f \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u043d\u0438\u0437\u0438\u043b \u0437\u0430\u0442\u0440\u0430\u0442\u044b \u043d\u0430 \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0439 \u0441\u0435\u0442\u043a\u0438 (\u043f\u043e \u0441\u0443\u0442\u0438, \u043e\u043d\u0430 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0432\u043b\u0438\u044f\u0442\u044c \u043d\u0430 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433).<\/p>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0414\u0430\u043d\u043d\u0430\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u0437\u0430\u043d\u044f\u043b\u0430 \u0443 \u043c\u0435\u043d\u044f \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u043d\u0430 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435, \u043d\u043e \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u044f \u0432\u0441\u0435 \u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u043b \u044d\u0442\u043e. \u041d\u0435 \u043c\u043e\u0433\u0443 \u0441\u0443\u0434\u0438\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 \u0432 \u0438\u0442\u043e\u0433\u0435 \u0443 \u043c\u0435\u043d\u044f \u0432\u044b\u0448\u0435\u043b, \u043d\u043e \u044f \u0434\u043e\u0432\u043e\u043b\u0435\u043d \u043e\u043f\u044b\u0442\u043e\u043c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u0437\u0430 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043d\u0438\u043c. \u0412 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, <strong>uViLEd<\/strong> \u044f \u0434\u043e \u0441\u0438\u0445 \u043f\u043e\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445. \u0427\u0442\u043e \u043a\u0430\u0441\u0430\u0435\u0442\u0441\u044f \u0432 \u0446\u0435\u043b\u043e\u043c \u0441\u0438\u0441\u0442\u0435\u043c \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043b\u043e\u0433\u0438\u043a\u0438, \u0442\u043e \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u044f \u044d\u0442\u043e\u0442 \u0433\u0435\u0448\u0442\u0430\u043b\u044c\u0442 \u0437\u0430\u043a\u0440\u044b\u043b. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u0435\u0441\u044c \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439, \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u043d\u044b\u0439 \u044d\u0442\u043e\u0439 \u0442\u0435\u043c\u0435, \u0431\u044b\u043b \u043a\u043e\u043c\u0443-\u043b\u0438\u0431\u043e \u043f\u043e\u043b\u0435\u0437\u0435\u043d, \u0438 \u043e\u043d \u0432\u044b\u043d\u0435\u0441\u0435\u0442 \u0438\u0437 \u043d\u0435\u0433\u043e, \u0447\u0442\u043e-\u0442\u043e \u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0434\u043b\u044f \u0441\u0435\u0431\u044f.<\/p>\n<p><strong>PS<\/strong>: \u043f\u043e\u043b\u043d\u044b\u0439 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u044f\u0434\u0440\u0430 \u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432 <a href=\"https:\/\/assetstore.unity.com\/packages\/slug\/208860\" rel=\"noopener noreferrer nofollow\">Asset Store<\/a>. \u0412\u0435\u0440\u0441\u0438\u044f \u0434\u043b\u044f \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0442\u043e\u0436\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 <a href=\"http:\/\/u3d.as\/1qVa\" rel=\"noopener noreferrer nofollow\">Asset Store<\/a>.<\/p>\n<p><strong>PS2<\/strong>: \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044f \u043e\u0434\u0438\u043d \u0433\u0435\u0448\u0442\u0430\u043b\u044c\u0442, \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0448\u044c \u043d\u043e\u0432\u044b\u0439, \u0442\u0435\u043f\u0435\u0440\u044c \u044f \u0445\u043e\u0447\u0443 \u043e\u043a\u0443\u043d\u0443\u0442\u044c\u0441\u044f \u0432 \u043c\u0438\u0440 <strong>JobSystem<\/strong> \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/div>\n<\/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\/post\/595009\/\"> https:\/\/habr.com\/ru\/post\/595009\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\" class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e \u0412\u0430\u0441, \u0443\u0432\u0430\u0436\u0430\u0435\u043c\u044b\u0435 \u0447\u0438\u0442\u0430\u0442\u0435\u043b\u0438. \u0412 \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u0448\u043d\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0432 \u0441\u0435\u0440\u0438\u0438 \u043e \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043b\u043e\u0433\u0438\u043a\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u043d\u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u0440\u0435\u0447\u044c \u043f\u043e\u0439\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e \u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435. \u0414\u0430\u043d\u043d\u044b\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0446\u0435\u043b\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u043c \u0438 \u043e\u0431\u0448\u0438\u0440\u043d\u044b\u043c, \u0432 \u0442\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0438 \u043f\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u042f \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u0440\u0430\u0441\u043a\u0440\u044b\u0442\u044c \u0432\u0441\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0442\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u043a\u0438\u0445 \u0432\u0435\u0449\u0435\u0439, \u043a\u0430\u043a \u0440\u0438\u0441\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0432\u044f\u0437\u0435\u0439, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 \u0438 \u0442. \u043f. <\/p>\n<p>\u041f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0441\u0442\u0430\u0442\u044c\u0438 \u0432 \u0441\u0435\u0440\u0438\u0438:<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/448190\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f Unity3d. \u0427\u0430\u0441\u0442\u044c 1<\/a><\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/466187\/\" rel=\"noopener noreferrer nofollow\">\u0412\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043b\u043e\u0433\u0438\u043a\u0438 \u0434\u043b\u044f Unity3d. \u0427\u0430\u0441\u0442\u044c 2<\/a><\/p>\n<h2>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h2>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0430 \u043e\u0431\u043e\u0431\u0449\u0435\u043d\u043d\u0430\u044f \u0441\u0445\u0435\u043c\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443, \u0447\u0442\u043e \u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u0447\u0442\u043e \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0432\u0430\u0436\u043d\u043e\u043c \u043c\u043e\u043c\u0435\u043d\u0442\u0435 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u0441 <strong>Unity<\/strong>. \u042f \u0434\u0443\u043c\u0430\u044e, \u043c\u043d\u043e\u0433\u0438\u043c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e \u043e\u0431 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f <strong>Unity3D<\/strong>, \u043d\u043e \u044f \u0432\u0441\u0435 \u0436\u0435 \u043e\u043f\u0438\u0448\u0443 \u0438\u0445:<\/p>\n<ol>\n<li>\n<p>\u041e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0447\u0435\u043d\u044c \u043a\u0440\u0438\u0432\u0430\u044f \u0438 \u0441\u0442\u0440\u0430\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<\/li>\n<li>\n<p>\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 (<strong>Coroutine<\/strong>).<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u0442\u0435\u043f\u0435\u0440\u044c \u043e\u043d\u0430 \u0435\u0441\u0442\u044c, \u043d\u043e, \u043a\u043e\u0433\u0434\u0430 \u043f\u0438\u0441\u0430\u043b\u0441\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440, \u0435\u0451 \u043d\u0435 \u0431\u044b\u043b\u043e<\/em>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u0432\u044b\u0448\u0435\u043e\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u044b\u043b\u043e \u0440\u0435\u0448\u0435\u043d\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0438 \u043a\u043e\u0434 \u043c\u0435\u0436\u0434\u0443 \u0434\u0432\u0443\u043c\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c\u0438 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u043c\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u043a\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 <strong>Unity3d.<\/strong><\/p>\n<\/li>\n<\/ol>\n<p>\u0412\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u043e\u0434\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u0432 \u044d\u0442\u0438 \u0434\u0432\u0435 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442\u0441\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u043f\u0440\u0438\u0432\u0430\u0442\u043d\u044b\u0445 \u043a\u043b\u0430\u0441\u0441\u043e\u0432. <\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<ul>\n<li>\n<p><strong>VLELogicEditor<\/strong>. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043b\u0430\u0441\u0441 \u043e\u043a\u043d\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043b\u043e\u0433\u0438\u043a\u0438<\/p>\n<ul>\n<li>\n<p><strong>MainMenu<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043c\u0435\u043d\u044e \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>LogicArea<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0449\u0438\u0439 \u0437\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>Status<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>VLECatalog<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u0441\u0431\u043e\u0440\u0430 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u0432\u0441\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438, \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0435.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEInspector<\/strong>. \u041a\u043b\u0430cc, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0430 <strong>Unity3D<\/strong><\/p>\n<ul>\n<li>\n<p><strong>VLELogicComponentCustomEditor<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043e\u0431\u0449\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0438\u043d\u0441\u043f\u0435\u043a\u0442\u043e\u0440\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>VLEObjectEditor<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0441\u0441\u044b\u043b\u043e\u043a \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b <strong>Unity3d<\/strong>. \u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u044d\u0442\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u0434\u043b\u044f \u043e\u0431\u0435\u0440\u0442\u043a\u0438 <strong>VLObject<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>VLESettingWindow<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u043a\u043d\u0430 \u043e\u0431\u0449\u0438\u0445 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043a \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>VLESearchWindow<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043f\u043e\u0438\u0441\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0438 \u0433\u0440\u0443\u043f\u043f \u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0444\u0430\u0439\u043b\u0435 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEWidget<\/strong>. \u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<ul>\n<li>\n<p><strong>VLEComponent<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p> <strong>VLEGroup<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0433\u0440\u0443\u043f\u043f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>VLELink<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u0432\u044f\u0437\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>VLEVariable<\/strong>. \u041a\u043b\u0430\u0441\u0441, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0439 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>\u0414\u043b\u044f \u043b\u0443\u0447\u0448\u0435\u0433\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f, \u0447\u0442\u043e \u0433\u0434\u0435 \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442, \u043d\u0438\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0430 \u043a\u0430\u0440\u0442\u0438\u043d\u043a\u0430.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u044b\u0439 \u043a\u043e\u0434 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043d\u0438\u0436\u0435\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u043f\u0443\u043d\u043a\u0442\u0430\u0445.<\/p>\n<h2>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0432 \u044f\u0434\u0440\u0435<\/h2>\n<p>\u0412 \u0445\u043e\u0434\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432\u0438\u0437\u0443\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u0442\u043e\u043b\u043a\u043d\u0443\u0442\u044c\u0441\u044f \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u0434\u043b\u044f \u0435\u0433\u043e \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0432\u0435\u0449\u0435\u0439 \u0432 \u044f\u0434\u0440\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 <strong>Unity3D<\/strong>. \u0421 \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u0431\u044b\u043b\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u043a\u043e\u0434, \u043e \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043d\u0438\u0436\u0435. \u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c \u044f\u0434\u0440\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u044f\u0434\u0440\u043e \u0434\u043b\u044f \u0431\u0438\u043b\u0434\u0430 \u0431\u044b\u043b\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0430 \u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430 \u043f\u0440\u0435\u0434\u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438 <em>UNITY_EDITOR<\/em>.<\/p>\n<h3>\u0421\u043f\u0438\u0441\u043e\u043a \u0444\u0430\u0439\u043b\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u0441\u0446\u0435\u043d\u0435<\/h3>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u0441\u0442\u0440\u043e \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0436\u0434\u0443 \u043d\u0430\u0431\u043e\u0440\u0430\u043c\u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u0432 \u0441\u0446\u0435\u043d\u0435, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0433\u0434\u0435-\u0442\u043e \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0438\u0445 \u0438\u043c\u0435\u043d\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0442\u0435\u043c \u0431\u044b\u043b\u0438 \u0431\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u044b \u0432 \u0432\u044b\u043f\u0430\u0434\u0430\u044e\u0449\u0435\u043c \u0441\u043f\u0438\u0441\u043a\u0435.<\/p>\n<p>\u0421 \u044d\u0442\u043e\u0439 \u0446\u0435\u043b\u044c\u044e \u0434\u043b\u044f \u0440\u0435\u0436\u0438\u043c\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0432 \u043a\u043b\u0430\u0441\u0441 <strong>LogicController<\/strong> \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR public string[] LogicVisualNames => SceneLogicList.ConvertAll(item => item.Name).ToArray();\u00a0\u00a0\u00a0\u00a0\u00a0  #endif<\/code><\/pre>\n<p>\u041d\u0438\u0436\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e \u043a\u0430\u043a \u044d\u0442\u043e\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0414\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432<\/h3>\n<p>\u0412 \u0445\u043e\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u0441 \u0446\u0435\u043b\u044c\u044e \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043b\u043e\u0433\u0438\u043a\u0438. \u042d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0431\u0438\u043b\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0434\u043e\u0441\u0442\u0443\u043f \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d \u043a\u0430\u043a \u0431\u044b\u043b\u043e \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0440\u0430\u043d\u0435\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR  public IDictionary&lt;string, LogicComponent> RuntimeComponentInstances = new Dictionary&lt;string, LogicComponent>(); #endif<\/code><\/pre>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b \u0432 \u044d\u0442\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR foreach (var componentInstance in instances) { RuntimeComponentInstances.Add(componentInstance.Key, componentInstance.Value); } #endif<\/code><\/pre>\n<h3>\u0420\u0430\u0431\u043e\u0442\u0430 \u0441\u043e \u0441\u0441\u044b\u043b\u043a\u0430\u043c\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity<\/h3>\n<p>\u0414\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u043e\u0431\u0435\u0440\u0442\u043a\u0438 \u043d\u0430\u0434 \u043e\u0431\u044a\u0435\u043a\u0442\u0430\u043c\u0438 <strong>Unity<\/strong>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>VLObject<\/strong>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u0440\u044f\u0434 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432:<\/p>\n<ol>\n<li>\n<p>\u0421\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u0435\u0440\u0436\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 <strong>Unity<\/strong> \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u0445 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u0442 \u043d\u0438 \u043e\u0434\u043d\u043e\u0439 \u0441\u0441\u044b\u043b\u043a\u0438 \u0438 \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0438\u0437 \u043a\u044d\u0448\u0430. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 \u043a\u043b\u0430\u0441\u0441\u0435 <strong>ObjectLinkData<\/strong> \u0437\u0430\u0432\u0435\u0434\u0435\u043c \u043f\u043e\u043b\u0435:<\/p>\n<pre><code class=\"cs\">#if UNITY_EDITOR public int Holders; #endif<\/code><\/pre>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432 \u0431\u0438\u043b\u0434\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b Unity \u043f\u043e \u0441\u0443\u0442\u0438 \u0441\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b, \u0442\u043e \u0442\u0430\u043c \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0438\u0445 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0438\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437\u0432\u043d\u0435. \u041e\u0434\u043d\u0430\u043a\u043e \u0434\u043b\u044f \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0441\u0430\u043c\u043e\u0439 \u0441\u043e\u0431\u043e\u0439 \u044d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u043d\u0443\u0436\u0435\u043d, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u043e\u043d \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0435\u0442\u043e\u0434\u043e\u0432:<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">#if UNITY_EDITOR public string SetObject(string oldObjId, UnityEngine.Object newObj) {                   if (newObj == null)   {     RemoveObjectLink(oldObjId);      return string.Empty;   }   else   {     var linkData = _objectLinks.Find(link => link.Obj == newObj);                      if (linkData == null)                         {         linkData = new ObjectLinkData(Guid.NewGuid().ToString(), newObj);                            _objectLinks.Add(linkData);     }else     {       linkData.Holders++;        if (linkData.Id != oldObjId)       {           RemoveObjectLink(oldObjId);       }     }                                                                  return linkData.Id;   } }          private void RemoveObjectLink(string objectId) {     var linkData = _objectLinks.Find(link => string.Compare(link.Id, objectId, StringComparison.Ordinal) == 0);                if (linkData != null)   {     linkData.Holders--;        if (linkData.Holders &lt;= 0)       {       _objectLinks.Remove(linkData);       }     }   } #endif<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u043d\u043e \u043f\u043e \u043a\u043e\u0434\u0443, \u0438\u043c\u0435\u043d\u043d\u043e \u0437\u0434\u0435\u0441\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u0447\u0435\u0442\u0447\u0438\u043a \u0434\u0435\u0440\u0436\u0430\u0442\u0435\u043b\u0435\u0439 \u0441\u0441\u044b\u043b\u043a\u0438.<\/p>\n<h2>\u0420\u0438\u0441\u0443\u0435\u043c \u0433\u043b\u0430\u0432\u043d\u043e\u0435 \u043e\u043a\u043d\u043e \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430<\/h2>\n<h3>\u041a\u043e\u043d\u0432\u0435\u0439\u0435\u0440 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430<\/h3>\n<p>\u0421 \u0446\u0435\u043b\u044c\u044e \u0443\u043d\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0431\u044b\u043b \u0441\u043e\u0437\u0434\u0430\u043d \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code class=\"cs\">public interface IEditorDrawer { bool Draw(Rect container, bool lockInput); } <\/code><\/pre>\n<p>\u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u043e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0446\u0438\u043a\u043b \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 (<strong>OnGUI<\/strong> \u043c\u0435\u0442\u043e\u0434) \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">if (!EditorApplication.isCompiling) {     for (var i = 0; i &lt; _currentEditorDraw.Count; i++)     {         var editorDraw = _currentEditorDraw[i];          _inputLocked = editorDraw.Draw(position, _inputLocked);     }      RemoveInactiveEditorDraws();  _inputLocked = false; } else {     GUI.Label(new Rect(5f, 5f, position.width - 10f, 25f), \"wait for compiling...\"); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<ol>\n<li>\n<p>\u041e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u043e\u043b\u044c\u043a\u043e, \u0435\u0441\u043b\u0438 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440 \u043d\u0435 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b <strong>IEditorDraw<\/strong> \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 <strong>Rect<\/strong> \u043e\u043a\u043d\u0430 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430 \u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0444\u043b\u0430\u0433\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0432\u0432\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 <strong>true<\/strong> \u043b\u044e\u0431\u043e\u0439 \u0438\u0437 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0438\u0445 \u043e\u043a\u043e\u043d (\u0434\u0438\u0430\u043b\u043e\u0433\u043e\u0432\u044b\u0435, \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0438 \u0442.\u043f.) \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0438\u0437 \u043a\u043e\u043d\u0432\u0435\u0439\u0435\u0440\u0430, \u044d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0442\u043e\u0434\u0430 <strong>DrawEditor<\/strong>:<\/p>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void DrawEditor(IEditorDrawer drawEditor) { if (!_currentEditorDraw.Contains(drawEditor))   {   _currentEditorDraw.Add(drawEditor);   }else   {   _currentEditorDrawForDelete.Add(drawEditor);   }             }<\/code><\/pre>\n<\/div>\n<\/details>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u043e\u043a\u043d\u043e \u0443\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430, \u0442\u043e \u043e\u043d \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0443\u0436\u0435 \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <strong>RemoveInactiveEditorDraws<\/strong>:<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u041a\u043e\u0434<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"cs\">private void RemoveInactiveEditorDraws() { if (_currentEditorDrawForDelete.Count > 0) { for (var i = 0; i &lt; _currentEditorDrawForDelete.Count; i++) { var editorDraw = _currentEditorDrawForDelete[i];  (editorDraw as IDisposable)?.Dispose();  _currentEditorDraw.Remove(editorDraw); }                  _currentEditorDrawForDelete.Clear(); } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h3>\u0421\u043e\u0431\u044b\u0442\u0438\u044f<\/h3>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u043d\u0430 \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0438\u0437 C# &#8212; <strong>event\/delegate<\/strong>. \u0414\u0430\u043d\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d \u043f\u043e \u043f\u0440\u0438\u0447\u0438\u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u0438. \u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u043c \u043a\u043b\u0430\u0441\u0441\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0432\u0441\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430. \u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u044d\u0442\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e:<\/p>\n<ul>\n<li>\n<p><strong>SelectedComponentChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>SelectedLogicChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>SelectedLogicUpdated<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>ComponentActiveChanged<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>OpenLogicsStorage<\/strong> \u2013 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0430\u043a\u0436\u0435 \u0432 \u043a\u0430\u0436\u0434\u043e\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0435 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0430, \u0435\u0441\u043b\u0438 \u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u0442\u044c \u0441\u0432\u043e\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d \u043f\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u043d\u0438\u0445 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0430\u0445.<\/p>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0438 <strong>UI<\/strong> \u0441\u043e\u0431\u044b\u0442\u0438\u044f (\u043d\u0430\u0436\u0430\u0442\u0438\u044f, <strong>drag&amp;drop<\/strong> \u0438 \u0442. \u043f.). \u0412 \u0432\u0438\u0434\u0443 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0440\u0435\u043d\u0434\u0435\u0440 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u043e\u0432 \u043e\u0434\u043d\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439, \u0442\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0442\u0430\u043a\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0441\u043e\u043f\u0440\u044f\u0436\u0435\u043d\u0430 \u0441 \u0442\u0440\u0443\u0434\u043d\u043e\u0441\u0442\u044f\u043c\u0438:<\/p>\n<ol>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043c \u0436\u0435, \u0433\u0434\u0435 \u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433.<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u0440\u0435\u0434\u0430\u043a\u0442\u043e\u0440\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u044f \u043f\u043e \u0432\u0441\u0435\u043c, \u0442\u043e \u043e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e (\u043d\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0432\u0438\u0434\u0436\u0435\u0442\u0430\u043c\u0438, \u043a\u0430\u043a \u044d\u0442\u043e \u0435\u0441\u0442\u044c \u0432 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u0432\u043e\u043c <strong>Unity UI<\/strong>).<\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/strong>: <em>\u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434 Event.Use() \u0438 \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f EventType.Used, \u043e\u0434\u043d\u0430\u043a\u043e \u044d\u0442\u043e \u043f\u043e \u0440\u0430\u0437\u043d\u044b\u043c \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c \u0431\u044b\u0432\u0430\u0435\u0442 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e.<\/em><\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u0438\u0432\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0448\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 <strong>IEditorDraw<\/strong> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0444\u043b\u0430\u0433\u0430 \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0432\u043e\u0434 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u043c \u0432\u0438\u0434\u0436\u0435\u0442\u043e\u043c\/\u043e\u043a\u043d\u043e\u043c. <\/p>\n<h3>\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b<\/h3>\n<p>\u0413\u043b\u0430\u0432\u043d\u043e\u0435 \u043c\u0435\u043d\u044e<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043e\u0442\u0440\u0438\u0441\u043e\u0432\u043a\u0438 \u043c\u0435\u043d\u044e:<\/p>\n<pre><code class=\"cs\">private class MainMenuToolbar : IEditorDrawer, IDisposable {}<\/code><\/pre>\n<p>\u0418\u043a\u043e\u043d\u043a\u0438 \u0434\u043b\u044f \u043a\u043d\u043e\u043f\u043e\u043a \u0431\u0435\u0440\u0443\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 (\u0438\u0437 <strong>Unity<\/strong>) \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <strong>EditorGUIUtility.IconContent<\/strong>:<\/p>\n<pre><code class=\"cs\">_catalogIconContent = new GUIContent(EditorGUIUtility.IconContent(\"project\"));<\/code><\/pre>\n<p>\u0421\u0430\u043c\u0438 \u043a\u043d\u043e\u043f\u043a\u0438 \u0440\u0438\u0441\u0443\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0433\u043e <strong>GUILayout<\/strong><\/p>\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-326943","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326943","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=326943"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326943\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=326943"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=326943"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=326943"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}