Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

Розширена фізична інтерполяція

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

Винятки для автоматичної фізичної інтерполяції

Навіть якщо фізична інтерполяція активна, можуть виникнути локальні ситуації, коли вам буде корисно вимкнути автоматичну інтерполяцію для Node (або гілки SceneTree) і мати більш точний контроль над виконанням інтерполяції вручну.

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

../../../_images/physics_interpolation_mode.webp

It is worth noting that, both in 2D and 3D, physics interpolation is performed on the local transform of each instance. During rendering, interpolated local transforms are passed down to children.

This means that if a parent has physics_interpolation_mode set to On, but the child is set to Off, the child will still be interpolated if the parent is moving. Only the child's local transform is uninterpolated. Controlling the on / off behavior of nodes therefore requires some thought and planning.

Найпоширенішою ситуацією, коли ви можете виконати власну інтерполяцію, є камери.

Фотоапарати

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

Це тому, що глядачі дуже чутливі до руху камери. Наприклад, Camera3D, яка дещо перебудовується кожні 1/10 секунди (зі швидкістю 10 tps), часто буде помітною. Ви можете отримати набагато плавніший результат, переміщуючи камеру в кожному кадрі в _process і дотримуючись інтерпольованої цілі вручну.

Ручна інтерполяція камери

Переконайтеся, що камера використовує глобальний простір координат

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

Є два способи зробити це:

  1. Перемістіть Camera3D так, щоб він був незалежним від власної гілки, а не був дочірнім елементом рухомого об’єкта.

../../../_images/fti_camera_worldspace.webp
  1. Викличте Node3D.top_level і встановіть значення true, що змусить камеру ігнорувати перетворення свого батька.

Типовий приклад

Типовим прикладом спеціального підходу є використання look_at у Camera3D кожен кадр у _process(), щоб дивитися на цільовий вузол (наприклад, програвач).

Але є проблема. Якщо ми використовуємо традиційний get_global_transform() на «цільовому» вузлі Camera3D, це перетворення фокусуватиме Camera3D лише на цілі на поточному фізичному тику. Це не те, чого ми хочемо, оскільки камера буде стрибати на кожному фізичному кліку, коли ціль рухається. Незважаючи на те, що камера може оновлюватися кожного кадру, це не допомагає забезпечити плавний рух, якщо ціль змінює лише кожен фізичний тик.

get_global_transform_interpolated()

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

Ми можемо зробити це за допомогою функції Node3D.get_global_transform_interpolated. Це діє так само, як отримання Node3D.global_transform, але це дає вам інтерпольоване перетворення (під час виклику _process()).

Важливо

get_global_transform_interpolated() слід використовувати лише один або два рази для особливих випадків, таких як камери. Його не можна використовувати скрізь у вашому коді (як з міркувань продуктивності, так і для забезпечення правильного ігрового процесу).

Примітка

Окрім винятків, таких як камера, у більшості випадків ваша ігрова логіка має бути в _physics_process(). У логіці гри ви повинні викликати get_global_transform() або get_transform(), які дадуть поточне фізичне перетворення (у глобальному або локальному просторі відповідно), що зазвичай є тим, що вам потрібно для коду ігрового процесу.

Приклад ручного сценарію камери

Ось приклад простої фіксованої камери, яка слідує за інтерпольованою ціллю:

extends Camera3D

# Node that the camera will follow
var _target

# We will smoothly lerp to follow the target
# rather than follow exactly
var _target_pos : Vector3 = Vector3()

func _ready() -> void:
    # Find the target node
    _target = get_node("../Player")

    # Turn off automatic physics interpolation for the Camera3D,
    # we will be doing this manually
    set_physics_interpolation_mode(Node.PHYSICS_INTERPOLATION_MODE_OFF)

func _process(delta: float) -> void:
    # Find the current interpolated transform of the target
    var tr : Transform = _target.get_global_transform_interpolated()

    # Provide some delayed smoothed lerping towards the target position
    _target_pos = lerp(_target_pos, tr.origin, min(delta, 1.0))

    # Fixed camera position, but it will follow the target
    look_at(_target_pos, Vector3(0, 1, 0))

Мишачий погляд

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

У цій ситуації може бути краще вимкнути фізичну інтерполяцію для вузла камери (за допомогою Node.physics_interpolation_mode) і безпосередньо застосувати введення миші до обертання камери, а не застосовувати його в _physics_process.

Іноді, особливо з камерами, ви захочете використовувати комбінацію інтерполяції та неінтерполяції:

  • Камера від першої особи може розташувати камеру в місці розташування гравця (можливо, використовуючи Node3D.get_global_transform_interpolated), але керувати обертанням камери з погляду миші без інтерполяції.

  • Камера третьої особи може подібним чином визначати погляд (цільове розташування) камери за допомогою Node3D.get_global_transform_interpolated, але позиціонувати камеру за допомогою погляду миші без інтерполяції.

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

Вимкнення інтерполяції на інших вузлах

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

Мульти Meshes

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

Повна інформація міститься в документації MultiMesh.