Симуляция толпы в Babylon.js строится на работе с множеством агентов, каждый из которых обладает собственными свойствами и поведением. Агент в контексте 3D-сцены — это объект с позицией, ориентацией, скоростью и набором правил движения. Основная цель — создание правдоподобного поведения толпы без ручного управления каждым объектом.
Babylon.js предоставляет гибкую систему для управления большим числом объектов через Mesh, InstancedMesh и ThinInstance, что критически важно для производительности при тысячах агентов.
Агент реализуется как класс с набором ключевых свойств:
class Agent {
constructor(mesh, position, speed) {
this.mesh = mesh;
this.position = position.clone();
this.velocity = new BABYLON.Vector3(0, 0, 0);
this.speed = speed;
this.target = null;
}
setTarget(target) {
this.target = target.clone();
}
update(deltaTime) {
if (!this.target) return;
const direction = this.target.subtract(this.position).normalize();
this.velocity = direction.scale(this.speed);
this.position.addInPlace(this.velocity.scale(deltaTime));
this.mesh.position.copyFrom(this.position);
}
}
Ключевые моменты:
position хранит текущее положение агента в мире.velocity определяет направление и скорость
движения.update отвечает за перемещение агента по
направлению к цели с учетом времени между кадрами
(deltaTime).Использование отдельных Mesh для каждого агента становится неэффективным при сотнях и тысячах объектов. Для оптимизации применяются:
const baseMesh = BABYLON.MeshBuilder.CreateBox("agent", { size: 1 }, scene);
const agents = [];
for (let i = 0; i < 500; i++) {
const instance = baseMesh.createInstance("agent" + i);
const agent = new Agent(instance, new BABYLON.Vector3(Math.random()*50, 0, Math.random()*50), 1 + Math.random());
agents.push(agent);
}
Поведение толпы строится на нескольких принципах:
Следование цели (Goal Seeking) Агент движется к заранее заданной точке или движущемуся объекту. Используется нормализация вектора направления и умножение на скорость.
Разделение (Separation) Агент избегает столкновений с соседями, создавая вектор отталкивания от близких объектов:
function separation(agent, neighbors, desiredSeparation) {
let steer = new BABYLON.Vector3(0,0,0);
let count = 0;
for (let other of neighbors) {
const distance = BABYLON.Vector3.Distance(agent.position, other.position);
if (distance > 0 && distance < desiredSeparation) {
const diff = agent.position.subtract(other.position).normalize().scale(1/distance);
steer.addInPlace(diff);
count++;
}
}
if (count > 0) steer.scaleInPlace(1 / count);
return steer;
}
Выравнивание (Alignment) Агент старается двигаться в направлении среднего вектора скорости соседей, создавая согласованное движение группы.
Сближение (Cohesion) Агент стремится к среднему положению соседей, удерживая целостность группы.
Эти три принципа (Separation, Alignment, Cohesion) известны как Boids-модель, широко применяемая для симуляции поведения стаи или толпы.
Для реалистичного движения необходимо обновлять всех агентов каждый кадр:
scene.onBeforeRenderObservable.add(() => {
const deltaTime = engine.getDeltaTime() / 1000; // в секундах
for (let agent of agents) {
const sep = separation(agent, agents, 2);
agent.velocity.addInPlace(sep);
agent.update(deltaTime);
}
});
Дополнительно можно добавлять ограничения на скорость, плавное вращение и коллизии с препятствиями, чтобы движение выглядело естественно.
Агенты не должны проходить сквозь стены или объекты сцены. Для этого используются:
Пример интеграции NavMesh:
BABYLON.SceneLoader.ImportMesh("", "models/", "navmesh.glb", scene, (meshes) => {
const navMesh = meshes[0];
const navigationPlugin = new BABYLON.AStarNavigationPlugin();
const navSystem = new BABYLON.NavigationHelper(navMesh, navigationPlugin);
agents.forEach(agent => agent.setTarget(navSystem.getRandomPoint()));
});
Для создания эффекта настоящей толпы важно визуально различать агентов:
Пример анимации с AnimationGroup:
const walkAnim = scene.getAnimationGroupByName("Walk");
agents.forEach(agent => {
const anim = walkAnim.clone("WalkClone" + agent.mesh.name);
anim.start(true, 1.0, anim.from, anim.to, true);
});
Для больших толп (тысячи агентов) критично:
Эти методы позволяют симулировать правдоподобную толпу в Babylon.js без просадок FPS даже на сложных сценах.