Вступ
Чи коли-небудь ви хотіли відтворити ефект заплутаного коридору з нескінченними петлями, як у P.T Silent Hills, за допомогою Unity? Цей ефект, ідеально підходить для ігор жахів, змушує гравців сумніватися в реальності, коли вони нескінченно ходять по тому самому коридору.
У цьому підручнику ми досягнемо цього моторошного ефекту, використовуючи телепортацію гравця, плавно повертаючи його назад на початок коридору, коли він доходить до кінця. Я проведу вас через кожен етап, починаючи від налаштування сцени до написання скрипта, забезпечуючи, щоб навіть новачки могли слідувати.
Що вам знадобиться
- Unity (будь-яка остання версія).
- Базове розуміння скриптінгу в Unity.
Крок 1: Налаштування сцени
Спочатку створимо основний шматок коридору з відкритими кінцями, що складається зі стін, підлоги та стелі. Потім створимо обидва відрізки коридору для початку та кінця. Нарешті, ми з'єднаємо всі ці частини разом, щоб створити один цілісний коридор. Ви можете називати об'єкти на свій розсуд, це не має значення в цьому проєкті.
1. Створіть основний шматок коридору:
Спроектуйте шматок коридору з відкритими початковими та кінцевими точками, використовуючи 3D-об'єкти Unity, такі як Cube для стін, Plane для підлоги та стелі, а також будь-які додаткові елементи, які ви хочете додати (наприклад, меблі, картини, двері тощо). Переконайтеся, що початкова та кінцева точки коридору однакові. Більше про це нижче.
Приклад основного шматка коридору
2. Переконайтеся, що початок і кінець однакові:
Ключем до того, щоб телепортація виглядала плавно, є забезпечення того, щоб початок і кінець коридору були точно однаковими.
Я назвав ці частини коридору: HallwayStartSection і HallwayEndSection. Ви можете назвати їх як хочете.
3. Налаштуйте TriggerZone і TeleportZone
Створіть два однакових куби, які покривають всю ширину та висоту двох частин коридору, що ми тільки що створили.
Я називатиму ці два куби: TeleportZone і TriggerZone.
Прикріпіть куб TeleportZone до HallwayStartSection, а куб TriggerZone до HallwayEndSection.
Переконайтеся, що куби розташовані однаково в межах обох частин HallwayStartSection і HallwayEndSection.
Куб TeleportZone (позначений червоним кольором) та куб TriggerZone (позначений синім кольором) - це куби, до яких я відключив префаб. Для цього підручника я залишив префаб увімкненим і надав кожному кубу окремий колір, щоб їх було легко розрізнити.
Порада: Щоб обидві частини коридору залишалися ідеально вирівняними і однаковими, ви можете: дублювати HallwayStartSection і перейменувати дубль на HallwayEndSection. Це спрощує процес, оскільки вам потрібно буде моделювати лише одну частину коридору. Не забувайте перейменувати дубльований TeleportZone на TriggerZone.
Приклад
До TriggerZone (куб, позначений синім кольором) потрібно прикріпити компонент BoxCollider
, встановивши параметр “Is Trigger” в True.
Приклад
Нарешті, переконайтеся, що обидва TriggerZone і TeleportZone мають ось Z спрямовану на протилежну стіну коридору, інакше виникнуть проблеми в майбутньому.
4.
Snap all the pieces together:
Прикріпіть обидві частини HallwayStartSection та HallwayEndSection, які ви щойно створили, до основної частини коридору, як показано нижче жовтими позначками.
Переконайтеся, що об'єкти HallwayStartSection та HallwayEndSection знаходяться всередині об'єкта Hallway. Це зробить все більш структурованим.
Порада: Користуючись інструментом “Move Tool”, натисніть клавішу “V” і наведете курсор на нижній кут частини коридору. Натисніть ліву кнопку миші та перетягніть кути разом. Це дозволить легко розташувати їх на місце.
5. Налаштування гравця:
Додайте Player Controller з First-Person Controller (або використовуйте Starter Assets Unity для швидкого налаштування).
Важливо: Переконайтеся, що ваш Player Controller має тег “Player” .
Крок 2: Переконайтесь, що освітлення однакове між HallwayStartSection та HallwayEndSection
Щоб налаштувати освітлення, перейдіть до Window > Rendering > Lighting та відкрийте вкладку Environment. Змініть Environment Lighting Source на колір і встановіть колір яскраво-білим. Я також видалив напрямкове освітлення для простоти під час тестування.
Це налаштування працює для тестування, але якщо ви плануєте використовувати це в грі, вам слід дослідити кращі альтернативи для більш реалістичного та динамічного освітлення.
Крок 3: Створіть новий скрипт
Додайте новий скрипт до об'єкта TriggerZone (куб, позначений синім кольором) та назвіть його як хочете. Я називатиму свій TeleportPlayer.cs
Відкрийте новостворений скрипт.
Крок 3: Створення ефекту петлі
Трюк для створення ефекту циклічного коридору полягає в телепортації гравця безшовно з кінця коридору назад на початок.
Для цього ми напишемо простий скрипт, який буде визначати, коли гравець потрапляє в TriggerZone (куб, позначений синім кольором), і телепортувати його в TeleportZone (куб, позначений червоним кольором).
Нижче наведено покрокове пояснення процесу:
Скрипт
using UnityEngine;
public class PlayerTeleporter : MonoBehaviour
{
public Transform TeleportZoneObject;
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Vector3 localOffset = transform.InverseTransformPoint(other.transform.position);
Quaternion relativeRotation = TeleportZoneObject.rotation * Quaternion.Inverse(transform.rotation);
CharacterController cc = other.GetComponent();
if (cc != null)
{
cc.enabled = false;
other.transform.position = TeleportZoneObject.TransformPoint(localOffset);
other.transform.rotation = relativeRotation * other.transform.rotation;
cc.enabled = true;
}
Debug.Log("Player teleported to: " + other.transform.position);
}
}
}
Пояснення крок за кроком
1. Налаштування TeleportZone
public Transform TeleportZoneObject;
Що це робить: Це посилання на місце (тип Transform
) у світі гри, куди гравець буде телепортований.
2. Виявлення, коли гравець досягає TriggerZone
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
// Логіка телепортації тут
}
}
Що це робить: Зона тригера (наприклад, коллайдер) визначає, коли гравець потрапляє в неї. Це обробляється методом OnTriggerEnter
.
3.
Calculate the Player’s Relative Position:
Vector3 localOffset = transform.InverseTransformPoint(other.transform.position);
Що це робить: Обчислює розташування гравця відносно TriggerZone.
Чому: Це гарантує, що позиція гравця буде налаштована правильно, зберігаючи його відносне положення після телепортації.
Приклад: Якщо гравець знаходиться трохи зліва від центру зони, після телепортації він залишиться трохи зліва.
4. Відповідність орієнтації гравця:
Quaternion relativeRotation = TeleportZoneObject.rotation * Quaternion.Inverse(transform.rotation);
Що це робить: Обчислює, як має змінитися орієнтація гравця (направлення, в яке він дивиться) в залежності від орієнтації TeleportZone.
Приклад: Якщо TeleportZone обернута на 90 градусів вправо, гравець також обернеться на 90 градусів вправо.
Призначення Quaternion.Inverse
: Це компенсує або скасовує обертання зони тригера, дозволяючи обчислити необхідне коригування для вирівнювання орієнтації гравця відносно TeleportZone.
Чому важливо: Без цього гравець втратив би свою початкову орієнтацію та просто прийняв би точну орієнтацію TeleportZone.
Цей приклад демонструє, що якщо ви просто використовуєте Quaternion.Inverse для обертання Player Controller, гравець завжди дивитиметься в один бік, потрапивши в TriggerZone, незалежно від того, як обернутий початковий коридор.
5. Вимкнення CharacterController (або RigidBody):
CharacterController cc = other.GetComponent();
if (cc != null)
{
cc.enabled = false;
Що це робить: Тимчасово вимикає компонент CharacterController
гравця.
Чому: CharacterController
може заважати ручним змінам позиції гравця, тому його вимикають під час телепортації.
Якщо у контролера гравця використовується RigidBody
, ви можете зробити те саме, використовуючи цей код:
Rigidbody rb = other.GetComponent();
if (rb != null)
{
rb.isKinematic = true;
6. Збереження відносного положення гравця під час телепортації:
other.transform.position = TeleportZoneObject.TransformPoint(localOffset);
Що це робить: Переміщає гравця в обчислене місце в TeleportZone, зберігаючи його відносне положення.
Приклад: Стоячи трохи зліва від одного порталу, ви опинитеся трохи зліва від порталу призначення.
7. Вирівнювання орієнтації гравця після телепортації
other.transform.rotation = relativeRotation * other.transform.rotation;
Що це робить: Коригує орієнтацію гравця, щоб вона відповідала орієнтації TeleportZone.
Приклад: Якщо гравець трохи дивиться вправо в одному порталі, він буде дивитися вправо і в призначеному порталі, адаптуючи це до нової орієнтації.
8. Повторне включення CharacterController (або RigidBody):
cc.enabled = true;
Що це робить: Повторно включає CharacterController
гравця після телепортації.
Якщо ви використовуєте контролер гравця з RigidBody
, використовуйте це замість цього:
rb.isKinematic = true;
9. Налагодження:
Debug.Log("Player teleported to: " + other.transform.position);
Це необов'язково.
Виводить нову позицію гравця в консолі Unity, що допомагає перевірити, чи все працює належним чином.
Крок 4: Призначте об'єкт TeleportZone в скрипт
Перетягніть об'єкт TeleportZone
з панелі Hierarchy та помістіть його в порожнє поле “Teleport Zone Object” типу Transform
у скрипті PlayerTeleporter.cs
.
Крок 4: Перевірте те, що ви створили
Помістіть ваш Player Controller в сцену і перевірте, чи правильно працює телепортація.
Висновок
Вітаємо! Ви щойно створили зациклений коридор, натхнений P.T Silent Hills в Unity. Цей механізм може стати чудовим доповненням до ігор жахів або головоломок, утримуючи гравців в напрузі.
Якщо це було корисно, поділіться своїми творіннями або задавайте питання в коментарях нижче! Якщо у вас є поради щодо покращення цього контенту, будь ласка, залиште їх у коментарях!
Перекладено з: How to Create a Looping Hallway in Unity (Like P.T. Silent Hills)