.gdpr{position: fixed; top: 0; bottom: 0; left: 0; right: 0; background: rgba(0, 0, 0, 0.7);color: #333;z-index:9999999;line-height:1.3;height: 100vh;width: 100vw} .gdpr_w{padding: 2rem;background: #fff;max-width: 700px;width: 95%;margin: 5% auto;text-align: center;position:fixed;left: 0;right: 0;margin:10% auto;} .gdpr_t{margin-bottom:15px;} .gdpr_t h3{font-size: 30px;margin:0px 0 10px 0;} .gdpr_t p{font-size: 16px;line-height: 1.45;margin:0;} .gdpr_x {position: absolute; right: 24px; top: 16px; cursor:pointer;} .gdpr_yn{margin-top:10px;} .gdpr_yn form{display: inline;} .gdpr_yn button{background: #37474F;border: none;color: #fff;padding: 8px 30px;font-size: 13px;margin: 0 3px;} .gdpr_yn .gdpr_n{background: #fff;color: #222;border: 1px solid #999;} amp-consent{margin-left: 10px;top: 2px;width: auto;background: transparent;} .gdpr_fmi{ width:100%; font-size: 15px; line-height: 1.45; margin: 0; } #footer .gdpr_fmi span, .gdpr_fmi span { display: inline-block; } #footer .gdpr_fmi a{ color: #005be2; } @media(max-width:768px){ .gdpr_w{width: 85%;margin:0 auto;padding:1.5rem;} } @media(max-width:700px){ .gdpr_w{margin:0 auto; width: 85%;} } .gdpr_fmi a:before{ display:none; } .gdpr_w{width:100%;} .f-w-f2 { padding: 50px 0px; } footer amp-consent.amp-active { z-index:9999; display: initial; position: inherit; height:20px; width:100%; } body[class*="amp-iso-country-"] .amp-active{ display: contents; } #post-consent-ui { position: fixed; z-index: 9999; left: 45%; margin-top: 10px; top: 0; } @font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 400;src: local('Poppins Regular '), local('Poppins-Regular'), url(https://fonts.gstatic.com/s/poppins/v13/pxiEyp8kv8JHgFVrFJDUc1NECPY.ttf);}@font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 500;src: local('Poppins Medium '), local('Poppins-Medium'), url(https://fonts.gstatic.com/s/poppins/v13/pxiByp8kv8JHgFVrLGT9V1tvFP-KUEg.ttf);}@font-face { font-family: Poppins;font-display: optional;font-style: normal;font-weight: 700;src: local('Poppins Bold '), local('Poppins-Bold'), url(https://fonts.gstatic.com/s/poppins/v13/pxiByp8kv8JHgFVrLCz7V1tvFP-KUEg.ttf);}a.heateor_sss_amp{padding:0 4px}div.heateor_sss_horizontal_sharing a amp-img{display:inline-block}.heateor_sss_amp_instagram img{background-color:#624E47}.heateor_sss_amp_yummly img{background-color:#E16120}.heateor_sss_amp_youtube img{background-color:#ff0000}.heateor_sss_amp_buffer img{background-color:#000}.heateor_sss_amp_delicious img{background-color:#53BEEE}.heateor_sss_amp_facebook img{background-color:#3C589A}.heateor_sss_amp_digg img{background-color:#006094}.heateor_sss_amp_email img{background-color:#649A3F}.heateor_sss_amp_float_it img{background-color:#53BEEE}.heateor_sss_amp_linkedin img{background-color:#0077B5}.heateor_sss_amp_pinterest img{background-color:#CC2329}.heateor_sss_amp_print img{background-color:#FD6500}.heateor_sss_amp_reddit img{background-color:#FF5700}.heateor_sss_amp_stocktwits img{background-color:#40576F}.heateor_sss_amp_mewe img{background-color:#007da1}.heateor_sss_amp_mix img{background-color:#ff8226}.heateor_sss_amp_tumblr img{background-color:#29435D}.heateor_sss_amp_twitter img{background-color:#55acee}.heateor_sss_amp_vkontakte img{background-color:#5E84AC}.heateor_sss_amp_yahoo img{background-color:#8F03CC}.heateor_sss_amp_xing img{background-color:#00797D}.heateor_sss_amp_instagram img{background-color:#527FA4}.heateor_sss_amp_whatsapp img{background-color:#55EB4C}.heateor_sss_amp_aim img{background-color:#10ff00}.heateor_sss_amp_amazon_wish_list img{background-color:#ffe000}.heateor_sss_amp_aol_mail img{background-color:#2A2A2A}.heateor_sss_amp_app_net img{background-color:#5D5D5D}.heateor_sss_amp_baidu img{background-color:#2319DC}.heateor_sss_amp_balatarin img{background-color:#fff}.heateor_sss_amp_bibsonomy img{background-color:#000}.heateor_sss_amp_bitty_browser img{background-color:#EFEFEF}.heateor_sss_amp_blinklist img{background-color:#3D3C3B}.heateor_sss_amp_blogger_post img{background-color:#FDA352}.heateor_sss_amp_blogmarks img{background-color:#535353}.heateor_sss_amp_bookmarks_fr img{background-color:#E8EAD4}.heateor_sss_amp_box_net img{background-color:#1A74B0}.heateor_sss_amp_buddymarks img{background-color:#ffd400}.heateor_sss_amp_care2_news img{background-color:#6EB43F}.heateor_sss_amp_citeulike img{background-color:#2781CD}.heateor_sss_amp_comment img{background-color:#444}.heateor_sss_amp_diary_ru img{background-color:#E8D8C6}.heateor_sss_amp_diaspora img{background-color:#2E3436}.heateor_sss_amp_dihitt img{background-color:#FF6300}.heateor_sss_amp_diigo img{background-color:#4A8BCA}.heateor_sss_amp_douban img{background-color:#497700}.heateor_sss_amp_draugiem img{background-color:#ffad66}.heateor_sss_amp_dzone img{background-color:#fff088}.heateor_sss_amp_evernote img{background-color:#8BE056}.heateor_sss_amp_facebook_messenger img{background-color:#0084FF}.heateor_sss_amp_fark img{background-color:#555}.heateor_sss_amp_fintel img{background-color:#087515}.heateor_sss_amp_flipboard img{background-color:#CC0000}.heateor_sss_amp_folkd img{background-color:#0F70B2}.heateor_sss_amp_google_classroom img{background-color:#FFC112}.heateor_sss_amp_google_bookmarks img{background-color:#CB0909}.heateor_sss_amp_google_gmail img{background-color:#E5E5E5}.heateor_sss_amp_hacker_news img{background-color:#F60}.heateor_sss_amp_hatena img{background-color:#00A6DB}.heateor_sss_amp_instapaper img{background-color:#EDEDED}.heateor_sss_amp_jamespot img{background-color:#FF9E2C}.heateor_sss_amp_kakao img{background-color:#FCB700}.heateor_sss_amp_kik img{background-color:#2A2A2A}.heateor_sss_amp_kindle_it img{background-color:#2A2A2A}.heateor_sss_amp_known img{background-color:#fff101}.heateor_sss_amp_line img{background-color:#00C300}.heateor_sss_amp_livejournal img{background-color:#EDEDED}.heateor_sss_amp_mail_ru img{background-color:#356FAC}.heateor_sss_amp_mendeley img{background-color:#A70805}.heateor_sss_amp_meneame img{background-color:#FF7D12}.heateor_sss_amp_mixi img{background-color:#EDEDED}.heateor_sss_amp_myspace img{background-color:#2A2A2A}.heateor_sss_amp_netlog img{background-color:#2A2A2A}.heateor_sss_amp_netvouz img{background-color:#c0ff00}.heateor_sss_amp_newsvine img{background-color:#055D00}.heateor_sss_amp_nujij img{background-color:#D40000}.heateor_sss_amp_odnoklassniki img{background-color:#F2720C}.heateor_sss_amp_oknotizie img{background-color:#fdff88}.heateor_sss_amp_outlook_com img{background-color:#0072C6}.heateor_sss_amp_papaly img{background-color:#3AC0F6}.heateor_sss_amp_pinboard img{background-color:#1341DE}.heateor_sss_amp_plurk img{background-color:#CF682F}.heateor_sss_amp_pocket img{background-color:#f0f0f0}.heateor_sss_amp_polyvore img{background-color:#2A2A2A}.heateor_sss_amp_printfriendly img{background-color:#61D1D5}.heateor_sss_amp_protopage_bookmarks img{background-color:#413FFF}.heateor_sss_amp_pusha img{background-color:#0072B8}.heateor_sss_amp_qzone img{background-color:#2B82D9}.heateor_sss_amp_refind img{background-color:#1492ef}.heateor_sss_amp_rediff_mypage img{background-color:#D20000}.heateor_sss_amp_renren img{background-color:#005EAC}.heateor_sss_amp_segnalo img{background-color:#fdff88}.heateor_sss_amp_sina_weibo img{background-color:#ff0}.heateor_sss_amp_sitejot img{background-color:#ffc800}.heateor_sss_amp_skype img{background-color:#00AFF0}.heateor_sss_amp_sms img{background-color:#6ebe45}.heateor_sss_amp_slashdot img{background-color:#004242}.heateor_sss_amp_stumpedia img{background-color:#EDEDED}.heateor_sss_amp_svejo img{background-color:#fa7aa3}.heateor_sss_amp_symbaloo_feeds img{background-color:#6DA8F7}.heateor_sss_amp_telegram img{background-color:#3DA5f1}.heateor_sss_amp_trello img{background-color:#1189CE}.heateor_sss_amp_tuenti img{background-color:#0075C9}.heateor_sss_amp_twiddla img{background-color:#EDEDED}.heateor_sss_amp_typepad_post img{background-color:#2A2A2A}.heateor_sss_amp_viadeo img{background-color:#2A2A2A}.heateor_sss_amp_viber img{background-color:#8B628F}.heateor_sss_amp_wanelo img{background-color:#fff}.heateor_sss_amp_webnews img{background-color:#CC2512}.heateor_sss_amp_wordpress img{background-color:#464646}.heateor_sss_amp_wykop img{background-color:#367DA9}.heateor_sss_amp_yahoo_mail img{background-color:#400090}.heateor_sss_amp_yahoo_messenger img{background-color:#400090}.heateor_sss_amp_yoolink img{background-color:#A2C538}.heateor_sss_amp_youmob img{background-color:#3B599D}.heateor_sss_amp_gentlereader img{background-color:#46aecf}.heateor_sss_amp_threema img{background-color:#2A2A2A}.heateor_sss_vertical_sharing{position:fixed;left:11px;z-index:99999}.heateor-total-share-count .sss_share_count{color:#666;font-size:23px}.heateor-total-share-count .sss_share_lbl{color:#666}.amp-wp-enforced-sizes img[alt="Pinterest"]{background:#cc2329}.amp-wp-enforced-sizes img[alt="Viber"]{background:#8b628f}.amp-wp-enforced-sizes img[alt="Print"]{background:#fd6500}.amp-wp-enforced-sizes img[alt="Threema"]{background:#2a2a2a}.amp-wp-article-content .heateor_sss_vertical_sharing{left:5px}.amp-wp-article-content amp-img[alt="Pinterest"]{left:4px}.amp-wp-enforced-sizes img[alt="MySpace"]{background:#2a2a2a} amp-web-push-widget button.amp-subscribe { display: inline-flex; align-items: center; border-radius: 5px; border: 0; box-sizing: border-box; margin: 0; padding: 10px 15px; cursor: pointer; outline: none; font-size: 15px; font-weight: 500; background: #4A90E2; margin-top: 7px; color: white; box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.5); -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } a.heateor_sss_amp{padding:0 4px;}div.heateor_sss_horizontal_sharing a amp-img{display:inline-block;}.heateor_sss_amp_gab img{background-color:#25CC80}.heateor_sss_amp_parler img{background-color:#892E5E}.heateor_sss_amp_gettr img{background-color:#E50000}.heateor_sss_amp_instagram img{background-color:#624E47}.heateor_sss_amp_yummly img{background-color:#E16120}.heateor_sss_amp_youtube img{background-color:#ff0000}.heateor_sss_amp_teams img{background-color:#5059c9}.heateor_sss_amp_google_translate img{background-color:#528ff5}.heateor_sss_amp_x img{background-color:#2a2a2a}.heateor_sss_amp_rutube img{background-color:#14191f}.heateor_sss_amp_buffer img{background-color:#000}.heateor_sss_amp_delicious img{background-color:#53BEEE}.heateor_sss_amp_rss img{background-color:#e3702d}.heateor_sss_amp_facebook img{background-color:#0765FE}.heateor_sss_amp_perplexity img{background-color:#165962}.heateor_sss_amp_claude img{background-color:#D97757}.heateor_sss_amp_google_ai img{background-color:#000}.heateor_sss_amp_grok img{background-color:#000}.heateor_sss_amp_chatgpt img{background-color:#000}.heateor_sss_amp_digg img{background-color:#006094}.heateor_sss_amp_email img{background-color:#649A3F}.heateor_sss_amp_float_it img{background-color:#53BEEE}.heateor_sss_amp_linkedin img{background-color:#0077B5}.heateor_sss_amp_pinterest img{background-color:#CC2329}.heateor_sss_amp_print img{background-color:#FD6500}.heateor_sss_amp_reddit img{background-color:#FF5700}.heateor_sss_amp_mastodon img{background-color:#6364FF}.heateor_sss_amp_stocktwits img{background-color: #40576F}.heateor_sss_amp_mewe img{background-color:#007da1}.heateor_sss_amp_mix img{background-color:#ff8226}.heateor_sss_amp_tumblr img{background-color:#29435D}.heateor_sss_amp_twitter img{background-color:#55acee}.heateor_sss_amp_vkontakte img{background-color:#0077FF}.heateor_sss_amp_yahoo img{background-color:#8F03CC}.heateor_sss_amp_xing img{background-color:#00797D}.heateor_sss_amp_instagram img{background-color:#527FA4}.heateor_sss_amp_whatsapp img{background-color:#55EB4C}.heateor_sss_amp_aim img{background-color: #10ff00}.heateor_sss_amp_amazon_wish_list img{background-color: #ffe000}.heateor_sss_amp_aol_mail img{background-color: #2A2A2A}.heateor_sss_amp_app_net img{background-color: #5D5D5D}.heateor_sss_amp_balatarin img{background-color: #fff}.heateor_sss_amp_bibsonomy img{background-color: #000}.heateor_sss_amp_bitty_browser img{background-color: #EFEFEF}.heateor_sss_amp_blinklist img{background-color: #3D3C3B}.heateor_sss_amp_blogger_post img{background-color: #FDA352}.heateor_sss_amp_blogmarks img{background-color: #535353}.heateor_sss_amp_bookmarks_fr img{background-color: #E8EAD4}.heateor_sss_amp_box_net img{background-color: #1A74B0}.heateor_sss_amp_buddymarks img{background-color: #ffd400}.heateor_sss_amp_care2_news img{background-color: #6EB43F}.heateor_sss_amp_comment img{background-color: #444}.heateor_sss_amp_diary_ru img{background-color: #E8D8C6}.heateor_sss_amp_diaspora img{background-color: #2E3436}.heateor_sss_amp_dihitt img{background-color: #FF6300}.heateor_sss_amp_diigo img{background-color: #4A8BCA}.heateor_sss_amp_douban img{background-color: #497700}.heateor_sss_amp_draugiem img{background-color: #ffad66}.heateor_sss_amp_evernote img{background-color: #8BE056}.heateor_sss_amp_facebook_messenger img{background-color: #0084FF}.heateor_sss_amp_fark img{background-color: #555}.heateor_sss_amp_fintel img{background-color: #087515}.heateor_sss_amp_flipboard img{background-color: #CC0000}.heateor_sss_amp_folkd img{background-color: #0F70B2}.heateor_sss_amp_google_news img{background-color: #4285F4}.heateor_sss_amp_google_classroom img{background-color: #FFC112}.heateor_sss_amp_google_gmail img{background-color: #E5E5E5}.heateor_sss_amp_hacker_news img{background-color: #F60}.heateor_sss_amp_hatena img{background-color: #00A6DB}.heateor_sss_amp_instapaper img{background-color: #EDEDED}.heateor_sss_amp_jamespot img{background-color: #FF9E2C}.heateor_sss_amp_kakao img{background-color: #FCB700}.heateor_sss_amp_kik img{background-color: #2A2A2A}.heateor_sss_amp_kindle_it img{background-color: #2A2A2A}.heateor_sss_amp_known img{background-color: #fff101}.heateor_sss_amp_line img{background-color: #00C300}.heateor_sss_amp_livejournal img{background-color: #EDEDED}.heateor_sss_amp_mail_ru img{background-color: #356FAC}.heateor_sss_amp_mendeley img{background-color: #A70805}.heateor_sss_amp_meneame img{background-color: #FF7D12}.heateor_sss_amp_mixi img{background-color: #EDEDED}.heateor_sss_amp_myspace img{background-color: #2A2A2A}.heateor_sss_amp_netlog img{background-color: #2A2A2A}.heateor_sss_amp_netvouz img{background-color: #c0ff00}.heateor_sss_amp_newsvine img{background-color: #055D00}.heateor_sss_amp_nujij img{background-color: #D40000}.heateor_sss_amp_odnoklassniki img{background-color: #F2720C}.heateor_sss_amp_oknotizie img{background-color: #fdff88}.heateor_sss_amp_outlook_com img{background-color: #0072C6}.heateor_sss_amp_papaly img{background-color: #3AC0F6}.heateor_sss_amp_pinboard img{background-color: #1341DE}.heateor_sss_amp_plurk img{background-color: #CF682F}.heateor_sss_amp_pocket img{background-color: #ee4056}.heateor_sss_amp_polyvore img{background-color: #2A2A2A}.heateor_sss_amp_printfriendly img{background-color: #61D1D5}.heateor_sss_amp_protopage_bookmarks img{background-color: #413FFF}.heateor_sss_amp_pusha img{background-color: #0072B8}.heateor_sss_amp_qzone img{background-color: #2B82D9}.heateor_sss_amp_refind img{background-color: #1492ef}.heateor_sss_amp_rediff_mypage img{background-color: #D20000}.heateor_sss_amp_renren img{background-color: #005EAC}.heateor_sss_amp_segnalo img{background-color: #fdff88}.heateor_sss_amp_sina_weibo img{background-color: #ff0}.heateor_sss_amp_sitejot img{background-color: #ffc800}.heateor_sss_amp_skype img{background-color: #00AFF0}.heateor_sss_amp_sms img{background-color: #6ebe45}.heateor_sss_amp_slashdot img{background-color: #004242}.heateor_sss_amp_stumpedia img{background-color: #EDEDED}.heateor_sss_amp_svejo img{background-color: #fa7aa3}.heateor_sss_amp_symbaloo_feeds img{background-color: #6DA8F7}.heateor_sss_amp_telegram img{background-color: #3DA5f1}.heateor_sss_amp_trello img{background-color: #1189CE}.heateor_sss_amp_tuenti img{background-color: #0075C9}.heateor_sss_amp_twiddla img{background-color: #EDEDED}.heateor_sss_amp_typepad_post img{background-color: #2A2A2A}.heateor_sss_amp_viadeo img{background-color: #2A2A2A}.heateor_sss_amp_viber img{background-color: #8B628F}.heateor_sss_amp_wordpress img{background-color: #464646}.heateor_sss_amp_wykop img{background-color: #367DA9}.heateor_sss_amp_yahoo_mail img{background-color: #400090}.heateor_sss_amp_yahoo_messenger img{background-color: #400090}.heateor_sss_amp_youmob img{background-color: #3B599D}.heateor_sss_amp_gentlereader img{background-color: #46aecf}.heateor_sss_amp_threema img{background-color: #2A2A2A}.heateor_sss_amp_bluesky img{background-color:#0085ff}.heateor_sss_amp_threads img{background-color:#000}.heateor_sss_amp_raindrop img{background-color:#0b7ed0}.heateor_sss_amp_micro_blog img{background-color:#ff8800}.heateor_sss_amp amp-img{border-radius:999px;} .amp-logo amp-img{width:190px} .amp-menu input{display:none;}.amp-menu li.menu-item-has-children ul{display:none;}.amp-menu li{position:relative;display:block;}.amp-menu > li a{display:block;} /* Inline styles */ div.acss138d7{clear:both;}div.acssf5b84{--relposth-columns:3;--relposth-columns_m:2;--relposth-columns_t:2;}div.acssae964{aspect-ratio:1/1;background:transparent no-repeat scroll 0% 0%;height:150px;max-width:150px;}div.acss6bdea{color:#333333;font-family:Arial;font-size:12px;height:75px;}div.acsse3e3c{font-weight:bold;}amp-img.acss334b9{max-width:35px;} .icon-widgets:before {content: "\e1bd";}.icon-search:before {content: "\e8b6";}.icon-shopping-cart:after {content: "\e8cc";}
Шутер от первого лица (first-person shooter, FPS) — это жанр, в котором игрок использует оружие и смотрит на мир глазами персонажа. FPS-игры чрезвычайно популярны, что видно по успеху таких франшиз, как Call of Duty и Battlefield.
Unreal Engine изначально был создан для разработки FPS, поэтому вполне логично использовать его для создания такой игры. В этом туториале вы научитесь следующему:
Примечание: эта статья является десятой частью серии туториалов, посвящённых движку Unreal Engine:
Скачайте заготовку проекта и распакуйте её. Перейдите в папку проекта и откройте BlockBreaker.uproject. Вы увидите следующую сцену:
Зелёная стена состоит из множества целей. Когда им наносят урон, они становятся красными. Когда их здоровье достигает нуля, они исчезают. Красная кнопка заново устанавливает все цели.
Для начала нужно создать Pawn игрока.
Перейдите в папку Blueprints и создайте новый Blueprint Class. Выберите в качестве родительского класса Character и назовите его BP_Player.
Character — это разновидность Pawn, но с дополнительным функционалом, например, с компонентом CharacterMovement.
Этот компонент автоматически обрабатывает движение, например, ходьбу и прыжки. Мы просто вызываем соответствующую функцию, благодаря чему Pawn перемещается. В этом компоненте также можно задать переменные, такие как скорость ходьбы и прыжков.
Чтобы заставить Pawn двигаться, нам нужно знать, когда игрок нажимает клавишу движения. Для этого мы привяжем движение к клавишам W, A, S и D.
Примечание: если вы незнакомы с привязками, то можете прочитать о них в части туториала, посвящённой Blueprints. Привязкой клавиш мы определяем, какие клавиши будут выполнять действие.
Выберите Edit\Project Settings и откройте настройки Input.
Создайте два Axis Mappings под названием MoveForward и MoveRight. MoveForward будет управлять движением вперёд и назад. MoveRight — движением влево и вправо.
Для MoveForward замените клавишу на W. После этого создайте ещё одну клавишу и выберите S. Измените Scale для S на -1.0.
Примечание: если вы хотите подробнее узнать о поле Scale, прочитайте часть туториала, посвящённую Blueprints. В разделе «Значение оси и масштаб ввода» говорится, что это и как этим пользоваться.
Позже мы будем умножать значение масштаба на вектор forward Pawn. Это даст нам вектор, направленный вперёд при положительном масштабе. Если масштаб отрицателен, то вектор будет направлен назад. С помощью получившегося вектора можно будет двигать Pawn вперёд и назад.
Теперь нам нужно сделать то же для движения влево и вправо. Измените клавишу для MoveRight на D. Затем создайте новую клавишу и выберите для неё A. Измените Scale для A на -1.0.
Теперь, когда мы настроили привязки, нам нужно использовать их для движения.
Откройте BP_Player, а затем откройте Event Graph. Добавьте событие MoveForward (то, которое указано в списке Axis Events). Это событие будет выполняться в каждом кадре, даже если вы ничего не нажимаете.
Также оно будет подавать на выход значение Axis Value, которое равно заданным ранее значениям Scale. Оно будет подавать на выход 1 при нажатии на W и -1 при нажатии на S. Если не нажимать клавиши, то на выходе будет 0.
Далее нужно приказать Pawn двигаться. Добавьте Add Movement Input и соедините его следующим образом:
Add Movement Input будет получать вектор и умножать его на Scale Value. Это преобразует его в соответствующем направлении. Поскольку мы используем Character, то компонент CharacterMovement будет перемещать Pawn в этом направлении.
Теперь нам нужно указать направление движения. Так как мы хотим двигаться вперёд, то можем использовать Get Actor Forward Vector. При этом будет возвращаться вектор, направленный вперёд. Создайте его и соедините следующим образом:
Подведём итог:
Повторим процесс для MoveRight, но заменим Get Actor Forward Vector на Get Actor Right Vector.
Для проверки движения нужно задать Pawn по умолчанию в игровом режиме.
Нажмите на Compile и вернитесь в основной редактор. Откройте панель World Settings и найдите раздел Game Mode. Измените значение Default Pawn Class на BP_Player.
Примечание: если у вас нет панели World Settings, то перейдите в Toolbar и выберите Settings\World Settings.
Теперь при запуске игры вы автоматически будете использовать BP_Player. Нажмите на Play и воспользуйтесь клавишами W, A, S и D для движения по уровню.
Теперь мы создадим привязки для поворота головы.
Откройте Project Settings. Создайте ещё два Axis Mappings под названием LookHorizontal и LookVertical.
Замените клавишу для LookHorizontal на Mouse X.
Эта привязка будет выдавать положительное значение при перемещении мыши вправо, и наоборот.
Теперь изменим клавишу для LookVertical на Mouse Y.
Эта привязка будет выдавать положительное значение при перемещении мыши вверх, и наоборот.
Теперь нам нужно создать логику, чтобы смотреть вокруг.
Если у Pawn нет компонента Camera, то Unreal автоматически создаёт камеру за вас. По умолчанию, камера будет использовать поворот контроллера.
Примечание: если вы хотите узнать больше о контроллерах, то изучите наш туториал «Искусственный интеллект».
Несмотря на то, что контроллеры не являются физическими, у них всё равно есть свой поворот. Это значит, что можно направить взгляд Pawn и камеры в разных направлениях. Например, в игре от третьего лица персонаж и камера не всегда смотрят в одном направлении.
Для поворота камеры в игре от первого лица нам достаточно изменить поворот контроллерая.
Откройте BP_Player и создайте событие LookHorizontal.
Чтобы заставить камеру поворачиваться влево или вправо, нам нужно регулировать рыскание (yaw). Создайте Add Controller Yaw Input и соедините его следующим образом:
Теперь при горизонтальном движении мыши контроллер будет поворачиваться влево или вправо. Поскольку камера использует поворот контроллера, она тоже будет поворачиваться.
Повторите процесс для LookVertical, но замените Add Controller Yaw Input на Add Controller Pitch Input.
Если запустите игру сейчас, то заметите, что вертикальное движение камеры инвертировано. Это значит, что при движении мыши вверх камера будет смотреть вниз.
Если вы предпочитаете неинвертированное управление, то умножьте Axis Value на -1. Это инвертирует Axis Value, что инвертирует наклон контроллера.
Нажмите на Compile и нажмите Play. Оглянитесь вокруг с помощью мыши.
Теперь, когда всё движение и обзор готовы, пришла пора создавать оружие!
Помните, что при создании Blueprint Class можно выбрать родительский класс? Можно так же выбирать в качестве родительских собственные Blueprints. Это полезно, когда имеются разные типы объектов, обладающие общим функционалом или атрибутами.
Допустим, нам нужно создать разные типы автомобилей. Можно создать базовый класс автомобиля, содержащий такие переменные, как скорость и цвет. Затем можно создать классы (дочерние), которые будут использовать в качестве родительского базовый класс автомобиля. Каждый дочерний класс будет содержать те же переменные. Теперь у вас есть простой способ для создания машин с разными значениями скорости и цвета.
Этим же способом можно создавать оружие. Для этого необходимо для начала создать базовый класс.
Вернитесь в основной редактор и создайте Blueprint Class типа Actor. Назовите его BP_BaseGun и откройте.
Теперь мы создадим несколько переменных, задающих свойства оружия. Создайте следующие переменные типа float:
Примечание: по умолчанию значения всех переменных равны нулю, что вполне подходит для туториала. Однако если вы хотите, чтобы у новых классов оружия было другое значение по умолчанию, то его нужно задать в BP_BaseGun.
Теперь нам нужно физическое представление этого оружия. Добавьте компонент Static Mesh и назовите его GunMesh.
Пока не волнуйтесь о выборе статического меша. Мы займёмся этим в следующем разделе, где будем создавать дочерний класс оружия.
Нажмите на Compile и вернитесь в основной редактор. Для создания дочернего класса нажмите правой клавишей мыши на BP_BaseGun и выберите Create Child Blueprint Class.
Назовите его BP_Rifle и откройте. Откройте Class Defaults и задайте переменным следующие значения:
Это значит, что максимальный путь каждой пули будет равен 5000. Если она попадёт в актора, то нанесёт 2 единицы урона. При стрельбе очередями интервал перед каждым выстрелом будет равен не менее чем 0.1 секунды.
Теперь нам нужно указать меш, который будет использоваться оружием. Выберите компонент GunMesh и выберите для Static Mesh значение SM_Rifle.
Теперь оружие готово. Нажмите на Compile и закройте BP_Rifle.
Теперь мы создадим собственный компонент камеры. Он даст нам более удобное управление расположением камеры. Также он позволит нам присоединить оружие к камере, чтобы оно всегда находилось перед камерой.
Откройте BP_Player и создайте компонент Camera. Назовите его FpsCamera.
Позиция по умолчанию находится довольно низко, из-за чего игрок может почувствовать себя маленьким. Измените location камеры FpsCamera на (0, 0, 90).
По умолчанию, компоненты Camera не используют поворот контроллера. Чтобы исправить это, перейдите в панель Details и включите Camera Settings\Use Pawn Control Rotation.
Теперь нам нужно задать место, в котором должно находиться оружие.
Для создания местоположения оружия мы можем использовать компонент Scene. Эти компоненты идеально подходят для задания местоположений, потому что содержат только Transform. Выберите FpsCamera и создайте компонент Scene. Таким образом он прикрепится к камере. Назовите его GunLocation.
Благодаря тому, что мы прикрепили GunLocation к FpsCamera, оружие постоянно будет сохранять своё положение относительно камеры. Таким образом, мы всегда будем видеть оружие перед камерой.
Теперь присвоим location компонента GunLocation значения (30, 14, -12). Так мы расположим оружие впереди и слегка сбоку от камеры.
Затем зададим rotation значения (0, 0, -95). Когда мы прикрепим оружие, то будет казаться, что оно всегда направлено в центр экрана.
Теперь нам нужно создать оружие и прикрепить его к GunLocation.
Найдите Event BeginPlay и создайте Spawn Actor From Class. Выберите для Class значение BP_Rifle.
Поскольку нам нужно будет использовать оружие позже, мы сохраним его в переменной. Создайте переменную типа BP_BaseGun и назовите её EquippedGun.
Важно то, что переменная не имеет тип BP_Rifle, потому что игрок может иметь разные типы оружия, а не только одно. Если создать другой тип оружия, то мы не сможем хранить его в переменной типа BP_Rifle. Это будет похоже на то, что мы пытаемся засунуть круг в прямоугольное отверстие.
Выбрав для переменной тип BP_BaseGun, мы создали большое «отверстие», подходящее под многие «фигуры».
Теперь присвоим EquippedGun значение Return ValueSpawn Actor From Class.
Чтобы прикрепить оружие, мы можем использовать AttachToComponent. Создайте его и задайте для Location Rule и Rotation Rule значение Snap to Target. Благодаря этому оружие будет иметь то же местоположение и поворот, что и родитель.
Теперь создадим ссылку на GunLocation и соединим всё следующим образом:
Подведём итог:
Нажмите на Compile и нажмите Play. Теперь при создании игрока будет создаваться и оружие! При поворотах оружие будет всегда находиться перед камерой.
Теперь начинается интересное: мы будем стрелять! Чтобы проверить, попала ли куда-нибудь пуля, мы можем использовать трассировку прямых.
Трассировка прямых — это функция, получающая начальную и конечную точки (образующие прямую). Она проверяет каждую точку на прямой (от начала до конца), пока на что-нибудь не наткнётся. В играх для проверки попадания пули чаще всего используется такой способ.
Поскольку стрельба — это функция оружия, она должна выполняться в классе оружия, а не игрока. Откройте BP_BaseGun и создайте функцию Shoot.
Затем создайте два входа Vector и назовите их StartLocation and EndLocation. Они будут начальной и конечной точками трассировки прямых (которые мы будем передавать из BP_Player).
Трассировку прямых можно выполнять с помощью LineTraceByChannel. Этот нод проверяет попадания с помощью канала коллизий Visibility или Camera. Создайте его и соедините следующим образом:
Теперь нам нужно проверить, попадает ли во что-нибудь трассировка прямых. Создайте Branch и соедините его так:
При попадании Return Value будет выдавать на выход true, и наоборот.
Чтобы дать игроку наглядную обратную связь о том, куда попала пуля, можно использовать эффект частиц.
Сначала нам нужно получить местоположение попадания трассировки. Перетащите левой клавишей мышиOut Hit на граф. В меню выберите Break Hit Result.
Так мы создадим нод с разными контактами, относящимися к результатам трассировки прямой.
Создайте Spawn Emitter at Location и задайте для Emitter Template значение PS_BulletImpact. Затем соедините его Location с Location нода Break Hit Result.
Вот как это будет выглядеть:
Подведём итог:
Теперь, когда логика стрельбы завершена, нам нужно воспользоваться ею.
Для начала нам нужно создать привязку клавиш для стрельбы. Нажмите на Compile и откройте Project Settings. Создайте новую Axis Mapping под названием Shoot. Выберите для неё клавишу Left Mouse Button и закройте Project Settings.
Затем откройте BP_Player и создайте событие Shoot.
Чтобы проверить, нажимает ли игрок клавишу Shoot, нам достаточно проверить, равно ли значение Axis Value единице (1). Создайте выделенные ноды:
Затем создайте ссылку на EquippedGun и вызовите его функцию Shoot.
Теперь нам нужно вычислить начальную и конечную точки для трассировки прямой.
Во многих FPS пуля летит из камеры, а не из оружия. Так делают потому, что камеру уже и так идеально выровнена с прицелом. Поэтому если мы будем стрелять из камеры, то пуля гарантированно полетит туда, где находится курсор.
Примечание: некоторые игры всё-таки реализуют стрельбу из оружия. Однако для стрельбы ровно в прицел требуются дополнительные вычисления.
Создайте ссылку на FpsCamera и соедините её с GetWorldLocation.
Теперь нам нужна конечная точка. Не забывайте, что у оружия есть переменная MaxBulletDistance. Это значит, что конечная точка должна находится на расстоянии MaxBulletDistance единиц от камеры. Чтобы реализовать это, создайте выделенные ноды:
Затем соедините всё следующим образом:
Подведём итог:
Нажмите на Compile, а затем на Play. Удерживайте левую клавишу мыши, чтобы начать стрельбу.
Пока оружие стреляет в каждом кадре. Это слишком быстро, поэтому на следующем этапе мы уменьшим частоту стрельбы оружия.
Во-первых, нам нужна переменная, чтобы определить, может ли игрок стрелять. Откройте BP_Player и создайте переменную типа boolean с названием CanShoot. Задайте ей значение true по умолчанию. Если CanShoot равна true, то игрок может стрелять, и наоборот.
Замените раздел Branch на следующее:
Теперь игрок может стрелять только если нажата клавиша Shoot и переменная CanShoot равна true.
Теперь добавим выделенные ноды:
Нажмите на Compile и закройте BP_Player. Нажмите Play и проверьте новую частоты стрельбы.
Теперь мы научим цели и кнопку реагировать на пули. Это можно сделать, добавив им урон.
Каждый актор в Unreal имеет возможность получения урона. Однако вы можете выбирать сами, как актор будет на него реагировать.
Например, персонаж файтинга при получении урона будет терять здоровье. Однако некоторые объекты, например, воздушный шарик, могут не иметь здоровья. Тогда можно запрограммировать шарик, чтобы он взрывался при получении урона.
Для того, чтобы можно было управлять получением актором урона, нам сначала нужно применить урон. Откройте BP_BaseGun и добавьте Apply Damage в конце функции Shoot.
Теперь нам нужно указать, какому актору мы хотим наносить урон. В нашем случае это актор, в которого попадает трассировка прямой. Соедините Damaged Actor с Hit Actor нода Break Hit Result.
Наконец, нам нужно указать величину нанесённого урона. Получите ссылку на Damage и соедините её с Base Damage.
Теперь при вызове Shoot она будет наносить урон акторам, попавшим в трассировку прямой. Нажмите на Compile и закройте BP_BaseGun.
Теперь нам нужно обработать то, как актор получает урон.
Сначала мы обработаем то, как урон получают цели. Откройте BP_Target и создайте Event AnyDamage. Это событие выполняется, когда актор получает урон, не равный нулю.
Теперь вызовите функцию TakeDamage и соедините контакты Damage. Это вычтет здоровье из переменной Health цели и обновит цвет цели.
Теперь, когда цель получает урон, она теряет здоровье. Нажмите на Compile и закройте BP_Target.
Теперь нам нужно обработать то, как получает урон кнопка. Откройте BP_ResetButton и создайте Event AnyDamage. Затем вызовите функцию ResetTargets.
Это будет восстанавливать все цели при получении урона кнопкой. Нажмите на Compile и закройте BP_ResetButton.
Нажмите на Play и начните стрелять по целям. Если вы хотите восстановить цели, то выстрелите по кнопке.
Готовый проект можно скачать отсюда.
Хотя созданный в этом туториале FPS очень прост, его можно запросто расширить. Попробуйте создать больше оружия с разными типами частоты стрельбы и урона. Можете даже попробовать добавить функцию перезарядки!
В Unity используется производительный язык программирования C#. Благодаря C# и Mono – кроссплатформенной реализации .NET,…