Хороший спосіб відтворити звук, коли щось відбувається? Як це звучить?


10

Тому я думав про те, наскільки монолітними моїми заняттями приділяється багато часу. Наприклад, у методі Characterкласу Jumpможе бути посилання на об’єкт звукових ефектів і відтворювати його. Це само по собі добре, але коли враховуються фізика, анімація, зіткнення тощо, метод Jump стає величезним, і Characterклас має багато залежностей від багатьох різних речей. Все-таки це може бути добре. Однак що робити, якщо ми більше не хочемо грати звук, коли персонаж стрибає? Тепер ми повинні знайти той конкретний рядок коду в переплутаному Jumpкоді і прокоментувати його чи що завгодно.

Отже .. я думав ..

Що робити, якщо натомість був якийсь AudioSystemклас, і все, що він робив, було передплатити випадкові події, які його цікавлять в інших класах. Наприклад, Characterклас може мати Jumpedподію (статичну теж, я вважаю), яка піднімається в Characterкласі в методі. Тоді Characterклас не знав би нічого про маленький звуковий ефект, який відтворюється, коли персонаж стрибає. Це AudioSystemбув би просто величезний клас, до якого програміст міг би відступити, щоб підключити звукові ефекти з певними подіями, які трапляються в грі через використання статичних подій. Тоді, якщо він отримав занадто великий , він може бути відділений в підкласи , як EffectsAudioSystem, BackgroundAudioSystem, AmbientAudioSystemі так далі.

Тоді в варіантах гри можна встановити прапорець, щоб увімкнути або вимкнути такі звуки, і все, що потрібно зробити, це просто відключити цю систему з простим і єдиним булевим прапором. Ця ідея систем може також поширюватися на такі речі, як фізика, анімація тощо, до того моменту, коли більшість відповідей на ігри, отримані в результаті дій гравця, підключаються через ці складні та роз'єднані системи.

Гаразд, тож моє запитання може бути трохи розпливчастим, але як це звучить? Я насправді ніколи не чув про подібну систему розмов. Це все в мене в голові зараз без будь-якого кодування, зробленого до цих пір, можливо, це одна з тих "хороших в теорії, але не на практиці" видів угод. Чи працювала б така система з більшою грою чи вона врешті-решт розпадеться і стане навіть більшою мірою спагетті, ніж оригінальна система?


5
Здається, як здорова ідея :) (Більш серйозна примітка: використання повідомлень для спілкування між слабко пов'язаними підсистемами / класами, як правило, є гарною ідеєю дизайну)
bummzack

1
так це робиться, ви також повинні розмістити свою візуалізацію в окремому класі, якщо ви ще цього не зробили (як в, у вас не повинно бути функції draw () у класі символів).
дрета

Відповіді:


2

Повідомлення - це пекло налагодження та підтримання. Теоретично це звучить добре, але колись на практиці він стає безладним з великою кількістю дублюючих даних, що надсилаються навколо. Ефект стрибкового звуку потребуватиме набагато більше даних у кінці, наприклад, положення, швидкість, матеріал, на якому знаходиться персонаж, ви його називаєте, список буде довгим наприкінці.

Таким чином, або вам потрібно буде зібрати ці дані та надіслати їх до AudioManager через дуже конкретну подію / повідомлення із скопійованими в нього даними, або ви надішлете посилання на персонажа в повідомленні, щоб AudioManager отримав доступ до даних, як способи закінчуються безладним, і тепер аудіо-менеджер повинен вибрати звук для матеріалу-андеграунд тощо.

Тож наприкінці конкретна подія (яка є дуже специфічним класом лише для цього повідомлення) знову з'єднає ці класи. Не багато виграшів, і наприкінці у вас буде безладний великий список дуже специфічних подій / класів, які служать лише для надсилання даних, які вже існують, і можуть бути застарілими, і будуть страждати від усіх інших проблем дублюваних даних .

Таким чином, буде величезний список непотрібних класів, для підтримки яких вводиться глибока зв'язок між персонажем і AudioManager, за винятком того, що він зараз розпорошений по всьому вихідному коду. Не тільки в класах символів та аудіоменеджерів.

Ще гарна ідея роз'єднати свій код, але Повідомлення - це просто ще один спосіб глибокого з'єднання. Деякий код просто потрібно з'єднати, використовувати найпряміший спосіб їх з'єднання, не перенавантажуйте.


1
Як добре спроектована система обміну повідомленнями "просто ще один спосіб глибоких муфт"? Надсилання повідомлень - це абсолютний мінімальний зв'язок без об'єктів, які ніколи не спілкуються. Те, як ви його сконструювали, може спричинити проблеми, але якщо система займає лише звук, місцеположення та тип, вона вирішує всі його проблеми та вводить жодну із запропонованих вами проблем. Аудіосистема не повинна обчислювати, який звук потрібен, вона повинна абстрагуватися від усіх налаштувань і, переважно, питань дифузії. en.wikipedia.org/wiki/Coupling_(computer_programming)
ClassicThunder

1
@ClassicThunder справа в тому, що на практиці цей підхід не дуже масштабний. Це добре працює для простих додатків, і поки все, що вам потрібно, - це загальний PlaySoundEvent. Але питання стосується прослуховування AudioManager спеціалізованої події OnJump () - так персонаж може позбутися аудіороботи. Однак це не буде у випадку з простим PlaySoundEvent, оскільки персонаж повинен вибрати звук і надіслати його AudioManager, що приводить до недійсності початкової точки введення OnJumpEvent для позбавлення від аудіороботи.
Майк Семер

1
Однак, використовуючи OnJumpEvent, ви можете вибрати або додати посилання на персонаж до події, або скопіювати всі важливі дані з персонажа в подію. Звичайно, ви маєте рацію, остання не вводить глибокої зв'язку, але вона буде страждати від проблем з дублюванням даних та нового об'єкта передачі даних, який потрібно підтримувати, як і для всіх інших нових подій.
Майк Семер

1
-1 тому, що я погоджуюся з тим, що мати такі спеціалізовані повідомлення (OnJump), ймовірно, погана ідея, це просто довге "Ні це погана ідея" замість корисної інформації, щоб змусити людину зробити подія PlaySound, яка має ім'я звукового ефекту та тривимірної позиції та / або гучності, в якій він виник.
Джеймс

@James спасибі за вклад, я не мав на увазі використовувати події PlaySound, я мав на увазі, що події - це хороша абстракція для програми GUI-бази даних, але не практична для складної гри.
Майк Семер

2

Я не думаю, що система передачі повідомлень взагалі над інженером. Насправді це може значно полегшити роботу в польській фазі. Ви все робите правильно!

Те, що ви описали, саме те, що я зібрав для нашої гри Global Game Jam минулого року. Я відповідав за створення та редагування SFX та інтеграцію музики, яку я та інший композитор записали в гру таким чином, що не смокче.

Що в цьому підході з точки зору аудіо - це те, що він дозволяє робити ще багато цікавих речей зі своїм звуком. Якщо ви думаєте, що звуковий ефект у грі - це лише звуковий файл, гучність та панорамність, ви робите це неправильно.

Приклад

У нашій грі ви були динозавром, що летів на космічному кораблі, що бігав на планети, щоб набрати очки. Ми працювали у Flash, тому інфраструктура, керована даними, не була потрібна. AudioManager був класом, що складався з масиву статичних методів, єдиною метою яких було контролювати, які звуки трапляються у відповідь на ігрову подію.

Якби я писав це на C ++, тоді знадобилося б трохи більше часу, щоб абстрагувати всі можливі звуки поведінки, які могли б мати. Вимоги до повідомлення, що сповіщає систему, що відбулася дія, не були б надто складними. Просто знадобиться тип повідомлення, об’єкт походження чи об'єкт, на який впливає, доступ до якогось контексту стану гри та багато іншого. Протокол може зростати по мірі зростання потреб у грі. Природно, якщо ви все це зробите в реалізації в коді (як наш кричущий код GGJ), у вас є гірша проблема монолітного класу. Але це легко пом'якшити, створивши систему, керовану даними.

У будь-якому випадку, ось як наша ігрова аудіо система відреагувала на різні повідомлення:

  • Гравець стикається з планетою: Це спричинить звук вибуху планети, досить базовий. то відразу після того, як він буде запитувати запущений комбінований лічильник. Якби він був досить високим, він запланував би звуковий ефект, який слід відтворювати на півсекунди або близько того пізніше динозавра, який робить перемогу ревом. Також на задньому плані було обчислено значення випадкової популяції планети (щось на зразок 600 - 3000 - я не маю уявлення, чому саме цей діапазон був обраний; це був якийсь покинутий механік геймплея і все ще лежить навколо мене, щоб зробити аудіо цікавим), і тому я використав це для масштабування гучності далекого звуку криків (планетарних громадян, які зустрічають несвоєчасну долю).

  • Гравець утримує пробіл для прискорення. Після отримання цього звучання пролунав невеличкий звук штовхаючого двигуна, але одночасно низький гуркіт двигуна підскочив протягом 1,5 секунд. Система частинок також використовувала це для запуску випромінювача IIRC

  • Гравець відпускає пробіл для уповільнення: тепер, коли гравець відпустив пробіл, аудіосистема знала, що повинна збивати петлю двигуна назад. Якби у мене було більше часу, я б хотіла нанести на нього ще один звук, який був своєрідним примруженням звучання.

  • Гравець стикається зі злом космічної шахти: Космічні міни погані, тому не тільки є металевий ударний звук у поєднанні з вибухом (це просто запекло в один звук), але також є і випадково вибраний звук дизламування динозавра, який грає. Більше шансів вибрати більше "плачучих" звуків, коли здоров'я гравця знижується.

І без того весела гра стає захопленням, коли її саундтрек активний та динамічний, навіть із невеликими простими способами поведінки, як я описав вище. Так, є певна логістика, яка допоможе переконатися, що правильні дані передаються. Але ей, BFD. Це буде далеко не найскладніше, що вам доведеться писати в більшій кількості ігрового коду.

Насправді, FMOD і Wwise працюють так. У них немає центрального диспетчера повідомлень, але ви ефективно розміщуєте події в їх центральних системах, і вони реагують, відтворюючи звуковий ефект, який був попередньо розроблений аудіо-реалізатором в інструменті для створення тексту. Подумайте про це, як дати своїй грі диджею в прямому ефірі. Він сидить і дивиться, що відбувається, і спрацьовує звукові кліпи в потрібний час, щоб зробити цікаві речі, змішуючи їх, щоб вони добре вписувались у попереднє аудіо середовище.

[EDIT] Крім того, я бачу, що ви позначили цей C #. Це XNA, і якщо так, ви використовуєте XACT? Якщо ви використовуєте XNA, вам слід використовувати XACT.


1
Це може працювати для невеликого проекту, це може бути навіть весело. Однак у великому з них ви маєте величезну кількість класів повідомлень, які потрібно підтримувати, тоді як простий виклик функції мав би такий же ефект. Ось чому система подій не розширює масштаби, їй важко керувати тим більшим, який отримує проект.
Майк Семдер

1
До речі, ми працюємо з FMOD в моїй студії, немає повідомлення / події-системи, ви не надсилаєте події в FMOD, ви просто викликаєте c-функцію або метод c ++, щоб щось відтворити. Вони просто називають свої звуки "подіями", це не робить його системою подій, це лише термін, який вони використовують замість звуку.
Майк Семер

Ні, чому? Ви просто викликаєте функцію безпосередньо, а не використовуєте подію для передачі параметрів. Подія в кінці не що інше, як виклик функції, просто передача параметрів в об'єкт події, а не передача їх безпосередньо. Єдина відмінність - це нове непряме введення системою подій, але врешті-решт, його простий функціональний виклик, лише зайво ускладнений.
Майк Семер

@MaikSemder Як виклики методів не закінчуються у власному заплутаному павутинні? Крім того, я намагався відзначити цю різницю між системою подій та "подіями", якими користуються Wwise та FMOD. Я думаю, що складна звукова логіка не належить до класів ігрових об'єктів, а відведення звукової логіки таким чином, що інтерфейс схожий на диспетчеризацію події, полегшує багату звукову логіку. Я дійсно бачу невелику функціональну різницю між EventManager->dispatch("Sound:PlayerJump")та soundSystem->playFMODEvent("/MyGame/Player/Jump").
michael.bartnett

2
Можливо, буде користь від більш простого кодування, але це не безкоштовно, воно пов'язане з витратами на продуктивність, обслуговування та більш жорсткі налагодження. Моя думка, користь не варта для великих проектів. Ви маєте справу з набагато більшими об'єктами, ніж без подій, і за них доводиться платити. Єдине місце, яке я б розглядав, як використовувати систему повідомлень, - це міжпотокове спілкування для запобігання блокування між потоками.
Майк Семер

0

Я погоджуюся з Майком Семером, що система передачі повідомлень може бути надмірно інженерною (поки що так чи інакше).

Як я розумію, зараз ваш клас схожий на "монолітний клас" Бьорна, як це можна побачити в "Монолітному класі" тут .

Я пропоную вам прочитати цю статтю, і хоча система повноцінних компонентів наразі була б надмірною, якщо ви прочитаєте "Розщеплення решти", це повинно дати вам хороший спосіб абстрагувати свою поведінку і, зрештою, можливо, перейти до більш складної рішення. Це дасть вам гарну базу для початку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.