Процедурная анимация через скрипты

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

Процедурная анимация основана на вычислениях, выполняемых в реальном времени, которые изменяют свойства объектов. В отличие от традиционных анимаций, где ключевые кадры заранее определяются в редакторе, в процедурной анимации всё рассчитывается на лету. Для этого в PlayCanvas используется JavaScript, который позволяет задавать анимации через скрипты.

Структура и синтаксис скриптов

В PlayCanvas скрипты добавляются как компоненты к сущностям. Скрипт может быть создан с помощью редактора PlayCanvas, а затем привязан к объектам в сцене. Синтаксис прост и основывается на стандартном JavaScript. Важнейшие методы для работы с анимацией — это те, которые управляют временем, положением и трансформациями объектов.

Пример простого скрипта для перемещения объекта:

var MoveObject = pc.createScript('moveObject');

// Инициализация
MoveObject.prototype.initialize = function() {
    this.speed = 2;  // Скорость движения
};

// Обновление состояния
MoveObject.prototype.update = function(dt) {
    // Перемещение объекта вдоль оси X
    this.entity.translateLocal(this.speed * dt, 0, 0);
};

В данном примере, скрипт перемещает объект вдоль оси X с постоянной скоростью. Параметр dt (delta time) необходим для того, чтобы движение было независимым от частоты кадров.

Использование интерполяции

Для плавных анимаций часто используется интерполяция, которая позволяет вычислять промежуточные значения между двумя состояниями. В PlayCanvas можно использовать различные методы интерполяции для изменения свойств объектов, таких как позиция, цвет или размер.

Пример анимации с использованием линейной интерполяции:

var ScaleObject = pc.createScript('scaleObject');

// Инициализация
ScaleObject.prototype.initialize = function() {
    this.startScale = this.entity.getLocalScale();  // Начальный масштаб
    this.endScale = new pc.Vec3(2, 2, 2);  // Конечный масштаб
    this.duration = 3;  // Время анимации
    this.elapsedTime = 0;
};

// Обновление состояния
ScaleObject.prototype.update = function(dt) {
    this.elapsedTime += dt;

    // Линейная интерполяция масштаба
    var scale = pc.Vec3.lerp(this.startScale, this.endScale, this.elapsedTime / this.duration);
    this.entity.setLocalScale(scale);

    // Если время анимации вышло, сбросить
    if (this.elapsedTime >= this.duration) {
        this.elapsedTime = 0;
        var temp = this.startScale;
        this.startScale = this.endScale;
        this.endScale = temp;
    }
};

В данном примере используется метод lerp, который линейно интерполирует между начальным и конечным масштабом. Это позволяет объекту увеличиваться в размерах за определённый период времени.

Работа с вращением объектов

Вращение объектов также может быть выполнено с использованием процедурных методов. В PlayCanvas можно вращать объекты вокруг разных осей с помощью матриц трансформации или напрямую через методы вращения. Например, чтобы объект вращался вокруг оси Y, можно использовать следующий скрипт:

var RotateObject = pc.createScript('rotateObject');

// Инициализация
RotateObject.prototype.initialize = function() {
    this.rotationSpeed = 30;  // Скорость вращения в градусах в секунду
};

// Обновление состояния
RotateObject.prototype.update = function(dt) {
    // Вращение вокруг оси Y
    this.entity.rotate(0, this.rotationSpeed * dt, 0);
};

Здесь объект будет вращаться вокруг оси Y со скоростью 30 градусов в секунду. Вращение также зависит от времени, что позволяет сделать анимацию независимой от частоты кадров.

Математические функции для анимации

Для создания более сложных анимаций, например, анимаций с синусоидальными движениями или возвратно-поступательными движениями, можно использовать математические функции. Например, для создания плавного синусоидального движения можно использовать функцию Math.sin для модификации позиции объекта.

Пример анимации с использованием синусоиды:

var SineMovement = pc.createScript('sineMovement');

// Инициализация
SineMovement.prototype.initialize = function() {
    this.amplitude = 5;  // Амплитуда движения
    this.frequency = 2;  // Частота
    this.startPosition = this.entity.getPosition();  // Начальная позиция
};

// Обновление состояния
SineMovement.prototype.update = function(dt) {
    var newX = this.startPosition.x + this.amplitude * Math.sin(this.frequency * pc.math.TWO_PI * this.app.time);
    this.entity.setPosition(newX, this.startPosition.y, this.startPosition.z);
};

В этом примере объект двигается по синусоиде вдоль оси X. Изменение позиции вычисляется с использованием функции Math.sin, что создаёт плавное возвратно-поступательное движение.

Сложные анимации с несколькими объектами

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

Пример анимации двух объектов:

var FollowObject = pc.createScript('followObject');

// Инициализация
FollowObject.prototype.initialize = function() {
    this.target = this.app.root.findByName('Target');  // Цель для следования
    this.speed = 5;  // Скорость следования
};

// Обновление состояния
FollowObject.prototype.update = function(dt) {
    // Вычисление направления к цели
    var direction = this.target.getPosition().clone().sub(this.entity.getPosition()).normalize();
    // Перемещение объекта к цели
    this.entity.translateLocal(direction.scale(this.speed * dt));
};

В этом примере один объект будет следовать за другим, вычисляя направление и перемещаясь с заданной скоростью.

Взаимодействие с физикой

Процедурная анимация также может быть интегрирована с системой физики PlayCanvas для более реалистичных движений объектов. Для этого можно использовать компоненты физики, такие как rigidbody и collision, а затем управлять их параметрами через скрипты.

Пример анимации с использованием физики:

var BounceObject = pc.createScript('bounceObject');

// Инициализация
BounceObject.prototype.initialize = function() {
    this.velocity = new pc.Vec3(0, 10, 0);  // Начальная скорость
};

// Обновление состояния
BounceObject.prototype.update = function(dt) {
    // Применение ускорения
    this.velocity.y -= 9.8 * dt;  // Ускорение свободного падения
    this.entity.translateLocal(this.velocity.x * dt, this.velocity.y * dt, this.velocity.z * dt);

    // Простая обработка отскока от земли
    if (this.entity.getPosition().y <= 0) {
        this.velocity.y = Math.abs(this.velocity.y) * 0.8;  // Отскок с потерей энергии
    }
};

Здесь объект будет падать и отскакивать от пола с учетом силы тяжести и потери энергии при отскоке.

Заключение

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