Tutorials

Силы и импульсы

Используйте клавиши курсора для применения импульсов, клавиши WASD для применения крутящих моментов и вращения куба. Нажмите и удерживайте F, чтобы применить постоянную силу вверх и отменить эффекты гравитации. Нажмите R, чтобы сбросить куб.

Попробуйте уравновесить куб и заставить его вращаться на одном из его углов! Полный код, использованный в этом примере, показан внизу этой страницы.

В этом уроке мы покажем вам, как использовать силы для управления динамическим твердотельным телом и создать демонстрацию, показанную выше. Мы кратко рассмотрим использование сил, импульсов, крутящих моментов и использование пользовательского интерфейса компонента твердотельного тела для настройки поведения.

Скриптование сил

Применение постоянной силы

if (app.keyboard.isPressed(pc.KEY_F) ) {
    this.entity.rigidbody.applyForce(0, 9.8, 0);
}

Здесь сила вдоль глобальной оси Y применяется к доступной сущности, когда пользователь нажимает клавишу F с помощью applyForce(x, y, z). Точка приложения вектора силы также может быть установлена.

Импульсы

if (app.keyboard.isPressed(pc.KEY_LEFT) ) {
    this.entity.rigidbody.applyImpulse(-1, 0, 0);
}

Кубу придается импульс по оси x для мгновенного изменения скорости с помощью applyImpulse(x, y, z).

Крутящие моменты

if (app.keyboard.isPressed(pc.KEY_W) ) {
    this.entity.rigidbody.applyTorque(-this.torque, 0, 0);
}

Крутящие моменты (вращательные силы) применяются к Entity с помощью applyTorque(x, y, z).

TorqueImpulses

this.entity.rigidbody.applyTorqueImpulse(x, y, z)

Мгновенные изменения угловой скорости применяются через applyTorqueImpulse(x, y, z). Это не использовалось в коде для демонстрации выше.

Перемещение динамических твердых тел

Для перемещения твердых тел вы применяете линейные силы и вращательные силы (крутящий момент) с использованием приведенных выше методов. Обычно вам следует избегать прямого изменения положения или скорости твердого тела, так как это будет переопределять симуляцию, и это может привести к странным эффектам, особенно при столкновении объектов.

Однако, если вам нужно, вы можете переопределить скорость, назначив новый набор значений 'pc.Vec3' напрямую на entity.rigidbody.linearVelocity или entity.rigidbody.angularVelocity.

Для получения дополнительной информации о типах твердых тел см. страницу API столкновений, страницу пространства имен pc, учебник по контроллеру fps и учебник по столкновениям.

Общая настройка

Мы настроили базовую сцену с прожектором, кубом (сущность с моделью, твердым телом, компонентами столкновения и сценариями) и полом (с моделью, твердым телом и компонентами столкновения). Твердое тело куба было установлено на динамическое, а твердое тело пола - на статическое. Мы создали некоторые материалы для каждого блока и изменили диффузные цвета, чтобы сделать его более приятным для глаз. Мы также активировали опцию "cast shadows" на обеих сущностях SpotLight и DynamicBody. Полная сцена "usingForces" и код для этого приложения PlayCanvas можно найти здесь.

Ограничение и контроль

Некоторые настройки редактора были установлены для предотвращения постоянного применения несбалансированных сил (и, таким образом, предотвращения непрерывного ускорения и выхода тела из-под контроля). Мы включили угловое затухание в редакторе атрибутов куба, а также трение на кубе и полу. Здесь не используется линейное затухание, однако оно может быть использовано для моделирования сопротивления воздуха, и, конечно же, замедления могут быть применены по мере необходимости через код.

rigidbody_settings

Телепортация тела

Чтобы мгновенно переместить тело в новую позицию, вы не можете использовать функцию setPosition из API pc.Entity. Это связано с тем, что физический движок все еще будет считать, что тело находится в старом месте. Вместо этого вам нужно использовать функцию телепорта компонента твердого тела:

// код внутри функции update
this.playerPos = this.entity.getLocalPosition();

// Удержание куба на экране - куб выходит за один край экрана, а затем появляется с противоположной стороны.
if (this.playerPos.x < -9.0) {
    this.entity.rigidbody.teleport(8.8, this.playerPos.y, this.playerPos.z);
}
if (this.playerPos.x > 9.0) {
    this.entity.rigidbody.teleport(-8.8, this.playerPos.y, this.playerPos.z);
}

Если куб перемещается за пределы видимой области в направлении x, вызывается функция телепортации, и куб Entity телепортируется через экран. Entity телепортируется в менее крайнее положение слева/справа, чтобы не активировать оператор if() непрерывно.

Код сброса куба

if (app.keyboard.wasPressed(pc.KEY_R)) {
    this.reset();
}

Issue Tracker

Новая функция: Tutorial Thumbnail

Описание

Добавить возможность загрузки изображения-миниатюры для обучающих материалов.

Задачи

Исправление ошибки: Entity не сохраняет Material Asset

Описание

При сохранении Entity, Material Asset не сохраняется вместе с ним.

Задачи

Улучшение: Material Inspector

Описание

Улучшить Material Inspector для более удобной работы с материалами.

Задачи

Улучшение: Node Inspector

Описание

Улучшить Node Inspector для более удобной работы с узлами графа.

Задачи

Улучшение: Assets

Описание

Улучшить систему работы с Assets для более удобного управления ресурсами.

Задачи

reset: function () {
    this.entity.rigidbody.teleport(0, 2, 0);
    this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
    this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
}

Мы включаем функцию сброса, которая возвращает куб в его исходное положение и, как упоминалось выше, синхронизирует местоположение твердого тела с местоположением телепортированной сущности. Последние две строки в функции сброса сбрасывают линейные и угловые скорости тела до нуля. Ориентация объекта также может быть сброшена, но это не выполняется в данном коде.

Полный список кода

var DynamicBody = pc.createScript('dynamicBody');

// инициализация кода, вызываемого один раз для каждой сущности
DynamicBody.prototype.initialize = function() {
    this.torque = 7;
    this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);

    this.on('destroy', function() {
        this.app.keyboard.off(pc.EVENT_KEYDOWN, this.onKeyDown, this);
    }, this);
};

DynamicBody.prototype.onKeyDown = function (event) {
    event.event.preventDefault();
};

// код обновления, вызываемый каждый кадр
DynamicBody.prototype.update = function(dt) {
    //обновление позиции игрока
    this.playerPos = this.entity.getLocalPosition();

    var app = this.app;

    //управление с клавиатуры и применение сил и моментов.
    if (app.keyboard.isPressed(pc.KEY_LEFT) ) {
        this.entity.rigidbody.applyImpulse(-1, 0, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_RIGHT) ) {
        this.entity.rigidbody.applyImpulse(1, 0, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_UP) ) {
        this.entity.rigidbody.applyImpulse(0, 1, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_A) ) {
        this.entity.rigidbody.applyTorque(0, this.torque, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_D) ) {
        this.entity.rigidbody.applyTorque(0, -this.torque, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_W) ) {
        this.entity.rigidbody.applyTorque(-this.torque, 0, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_S) ) {
        this.entity.rigidbody.applyTorque(this.torque, 0, 0);
    }
    if (app.keyboard.isPressed(pc.KEY_F) ) {
        this.entity.rigidbody.applyForce(0, 9.8, 0);
    }

    // Удержание куба на экране - куб перемещается с одного края экрана и появляется с противоположного края.
    if (this.playerPos.x < -9.0) {
        this.entity.rigidbody.teleport(8.8, this.playerPos.y, this.playerPos.z);
    }
    if (this.playerPos.x > 9.0) {
        this.entity.rigidbody.teleport(-8.8, this.playerPos.y, this.playerPos.z);
    }

    // контроль сброса куба
    if (app.keyboard.wasPressed(pc.KEY_R) ) {
        this.reset();
    }
};

DynamicBody.prototype.reset = function () {
    this.entity.rigidbody.teleport(0, 2, 0);
    this.entity.rigidbody.linearVelocity = pc.Vec3.ZERO;
    this.entity.rigidbody.angularVelocity = pc.Vec3.ZERO;
};
This site is translated by the community. If you want to get involved visit this page