userData: произвольные данные на объекте

В Three.js каждый объект сцены наследует свойство userData, представляющее собой объект JavaScript. Это специальное место для хранения произвольной информации, связанной с объектом, которая не влияет на рендеринг или поведение движка, но позволяет расширять объекты пользовательскими данными.

const mesh = new THREE.Mesh(geometry, material);
mesh.userData = {
    health: 100,
    name: 'Player1',
    isActive: true
};

В этом примере к объекту mesh добавлены произвольные поля: health, name, isActive. Они доступны в любой момент выполнения программы и могут использоваться для логики игры, анимации или управления взаимодействиями.


Особенности использования userData

  1. Произвольная структура данных userData может содержать любые типы данных: числа, строки, булевы значения, массивы, объекты и даже функции. Например:
mesh.userData.positionHistory = [];
mesh.userData.updateHistory = function(newPosition) {
    this.positionHistory.push(newPosition.clone());
};
  1. Не влияет на Three.js Все данные в userData полностью игнорируются самим движком при рендеринге. Это безопасное хранилище для метаданных, которое не замедляет визуализацию и не мешает встроенной логике объектов.

  2. Наследование и клонирование объектов При использовании метода clone() объект копируется вместе с userData:

const cloneMesh = mesh.clone();
console.log(cloneMesh.userData.name); // 'Player1'

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

  1. Использование в событиях и взаимодействиях userData часто применяют для хранения информации о взаимодействии с объектами: например, идентификаторы, состояния или параметры анимации. При обработке событий, таких как raycaster.intersectObjects(), данные из userData помогают определить контекст объекта:
const intersects = raycaster.intersectObjects(scene.children);
if (intersects.length > 0) {
    const obj = intersects[0].object;
    if (obj.userData.isActive) {
        console.log(`Активный объект: ${obj.userData.name}`);
    }
}
  1. Сериализация и сохранение Для сохранения состояния сцены userData можно сериализовать в JSON. Three.js поддерживает методы toJSON() и ObjectLoader, которые учитывают userData:
const sceneJSON = scene.toJSON();
const loadedScene = new THREE.ObjectLoader().parse(sceneJSON);

После загрузки объекты будут содержать те же пользовательские данные, что и до сериализации.


Практические советы

  • Минимализм и структурирование Лучше хранить в userData только необходимые данные и структурировать их объектами, чтобы не создавать хаотичных полей:
mesh.userData.game = {
    score: 10,
    level: 2,
    buffs: ['speed', 'shield']
};
  • Использование для логики игры и GUI Через userData удобно связывать объекты сцены с логикой приложения, UI или системой анимации, не засоряя основной код и не вмешиваясь в свойства Three.js объектов.

  • Глубокие копии при необходимости Если один объект клонируется для многократного использования с различными данными, следует создавать глубокие копии userData, чтобы избежать нежелательных ссылочных изменений.


Примеры применения

  1. Идентификация объектов для взаимодействий
mesh.userData.id = 'enemy_01';
mesh.userData.isTargetable = true;
  1. Хранение параметров анимации
mesh.userData.animation = {
    speed: 1.2,
    loop: true,
    startTime: Date.now()
};
  1. Отслеживание состояния игры
mesh.userData.status = {
    health: 80,
    mana: 50,
    isAlive: true
};

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