Всем привет!
Я недавно начала разбираться с Unreal Engine 5 и C++, хочу сделать свою первую игру. Суть такая: мне нужно, чтобы враги в игре могли реагировать на звук, например, если игрок уронит предмет, враги начнут искать источник звука, а их реакция будет зависеть от расстояния и уровня шума. Я уже подключила систему звуковых уведомлений через MakeNoise и перехватываю их в PawnSensingComponent. Но как сделать так, чтобы враг реагировал не мгновенно, а, скажем, через 2-3 секунды, и при этом выглядело, будто он действительно «прислушивается», а не сразу бежит в сторону звука? Еще хотелось бы добавить некое «сомнение», чтобы иногда враг не реагировал вовсе, если звук был слишком тихим. Я застряла и не знаю, как это правильно реализовать на C++. Как это можно реализовать? Какой подход лучше использовать: написать всё с нуля или использовать существующие системы движка?
Ох, ну, добро пожаловать, юная разработчица! Ты, видать, ещё не успела понять, во что ввязалась. Создать систему реагирования врагов на звуки — это как попросить кота принести газету: в принципе возможно, но довольно геморно.
Для начала, вот тебе два пути, которые можно назвать «путь Джедая» и «путь Ситха». Джедаи используют всё готовое из движка, а Ситхи — пишут своё, проклиная всю вселенную.
Если хочешь сделать по-простому, начни с Gameplay Ability System и Perception System. Там уже есть зрение, слух и даже нюх (да-да, враги могут учуять тебя, если постараться). Создаёшь источник звука как объект, бросаешь его в мир с помощью UAISense_Hearing, указываешь радиус и уровень шума — и готово. Враги начнут «слышать» это, как только ты подключишь им компонент AI Perception.
Задержка реакции на звук:
Старый дедовский способ: таймеры. Когда твой PawnSensingComponent услышит шум (событие OnHearNoise), вместо того чтобы сразу отправлять врага в режим «режим Чака Норриса», поставь таймер на 2-3 секунды.
Примерно так:
cpp:
void AYourAICharacter::OnNoiseHeard(APawn* NoiseInstigator,const FVector& Location,float Volume){if(NoiseInstigator){UE_LOG(LogTemp, Log,TEXT("Шум услышан! Ставим таймер на реакцию..."));// Ставим таймер для задержкиGetWorldTimerManager().SetTimer(ReactionTimerHandle,this,&AYourAICharacter::ReactToNoise,2.0f,false);// Сохраняем данные для обработки
LastNoiseLocation = Location;
NoiseVolume = Volume;}}void AYourAICharacter::ReactToNoise(){UE_LOG(LogTemp, Log,TEXT("Враг прислушался и начинает поиск!"));// Делаем что-то — например, отправляем врага искать источник шумаMoveToLocation(LastNoiseLocation);}
Тут вся магия — в таймере. SetTimer дает твоему ИИ возможность "обдумать" услышанный шум, что выглядит реалистично.
Эффект «сомнения» (случайное игнорирование):
Знаешь, даже у бывалого охранника иногда "глюки" случаются. Добавь элемент случайности через FMath::RandRange или FMath::FRand и настрой вероятность, с которой враг будет игнорировать слабый звук:
cpp:
void AYourAICharacter::ReactToNoise(){float IgnoreChance = FMath::FRand();// Случайное число от 0 до 1if(NoiseVolume <0.5f&& IgnoreChance >0.7f)// Тихий звук и 30% шанс на игнор{UE_LOG(LogTemp, Warning,TEXT("Враг подумал, что это мышь. Игнорируем шум."));return;// Ничего не делаем}UE_LOG(LogTemp, Log,TEXT("Враг прислушался и начинает поиск!"));MoveToLocation(LastNoiseLocation);}
Тут враг «задумается» на 2 секунды и с некоторой вероятностью решит, что это просто мышь или ветер шумит. Если звук достаточно громкий, игнорировать не будет.
Добавить анимацию «прислушивания»:
Если хочешь, чтобы враг визуально «прислушивался», запускай анимацию при старте таймера. Вызови метод для PlayAnimMontage или настрой анимационный Blueprint через Event.
Например:
cpp:
PlayAnimMontage(ListeningMontage);
Так твои враги будут не просто роботами, а настоящими детективами-аутистами!
Но если ты хочешь по-настоящему понять, на что способен Unreal (и свести себя с ума), то вставай на путь Ситха:
1. Заводи C++ класс для своего источника звука. Пусть он генерирует событие с координатами, уровнем шума и типом звука.
2. Создавай кастомный компонент для врагов, который будет подписываться на эти события и принимать решения, основываясь на расстоянии и интенсивности звука.
3. Пиши логику: если звук громкий и близко — враг должен бежать туда, если тихий и далеко — просто посмотреть в ту сторону.
Не забудь использовать FVector::Dist() для расчёта расстояния и FMath::Clamp() — чтобы никто из врагов не услышал падающую ложку за 2 километра. А чтобы красиво враги искали тебя, прикрути Behavior Tree и добавь кастомный таск вроде «идти на шум, как бабка к сериалу».
Короче, если коротко, путь Джедая проще, но путь Ситха веселее. Только не забудь, что враги, как и программисты, реагируют на баги куда сильнее, чем на звуки. Удачи! Если все еще путаешься, приходи снова в таверну стариков Unreal Engine, научим уму-разуму!
Привет, используй уже готовые, будет проще, зачем тратить море времени и не видя результата. Думаю будет уныло просидеть над этим год, а потом понять что херня вышла. Пользуйся сенсором уже готовым, а все твои вопросы через задержку например delay и остальные, time и тд, что бы не сразу реагировал. Сомнения можешь вообще через рандом, например если расстояния 100 метров бежит не думает, а если 150 -200 на рандоме выпадает нужное число пойдёт проверять, не выпадает ну гуляет дальше. Много Вариков есть. Рандом вноси уже 150 минимум а максимум 200 и если диапазон 150-170 выпадает пойдёт проверять выше постоит и дальше пойдет.
Попробуй просто в том объекте который издает звук создать функцию которая как бы будет создавать невидимый барьер который будет передавать нужным таргетам свою позицию а уже логику с получаемой позицией реализовывай в самом акторе который будет реагировать .