Частицы - это маленькие плоские картинки, которые в Minecraft повсюду: дым от костра, сердечки над довольным животным, пузырьки под водой. В этом гайде вы сделаете свою: рубиновую искру. Это вспышка маленьких красных огоньков, которые поднимаются вверх, мерцают и гаснут.
Вы узнаете, что пишется в файле частицы, как нарисовать её текстуру, как заставить её меняться со временем и как показать её в игре с помощью команды, анимации или скрипта.
Только пакет ресурсов
Частицы целиком живут в пакете ресурсов. Пакет поведения нужен не для того, чтобы её сделать, а только чтобы запускать её от моба или из скрипта. GodCraft сам пишет файлы пакета и манифесты: смотрите Экспорт и установка.
Файлы
RP/
particles/
ruby_sparkle.json
ruby_dust.json
textures/
particle/
ruby_sparkle.pngИгра загружает каждый файл .json из папки particles. Имя файла не важно, но если оно совпадает с именем частицы, всё легче найти.
Эмиттеры и частицы
Прежде чем что-то писать, полезно знать две части любого эффекта:
- Эмиттер - это невидимый спавнер. Он решает, сколько частиц появится, где они начнут путь и как долго он будет их создавать.
- Частицы - это маленькие картинки. Каждая решает, как она двигается, как выглядит и когда исчезает.
Поэтому компоненты частиц делятся на два семейства. Названия, которые начинаются с minecraft:emitter_, настраивают спавнер. Названия, которые начинаются с minecraft:particle_, настраивают каждую картинку. Писать их можно в любом порядке.
| Часть файла | Что в ней |
|---|---|
description | Имя частицы, а также её материал и текстура |
curves | Необязательно. Значения, которые меняются за время жизни частицы |
events | Необязательно. То, что происходит в определённые моменты, например появление новых частиц |
components | Всё остальное: настройки эмиттера и частиц |
Шаг 1: текстура
Нарисуйте PNG 8x8 и сохраните его как RP/textures/particle/ruby_sparkle.png. Хорошо подойдёт маленькая четырёхконечная звёздочка.
Рисуйте её белым и светло-серым, а не красным. Потом вы окрасите её в нужный цвет, а окрашивание умножает пиксели. Белый превращается в любой цвет, а вот красная картинка, окрашенная в синий, станет почти чёрной.
Оставьте фон полностью прозрачным. Частицы всегда плоские квадраты, так что форму им дают именно прозрачные пиксели.
Шаг 2: описание
Создайте файл частицы и начните с её имени и внешнего вида:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_sparkle",
"basic_render_parameters": {
"material": "particles_alpha",
"texture": "textures/particle/ruby_sparkle"
}
},
"components": {}
}
}identifier- имя, по которому вы запускаете частицу. Всегда давайте ей своё пространство имён (здесьwiki:), чтобы она никогда не пересеклась с ванилью или другим аддоном.texture- путь к вашему PNG от корня пакета ресурсов, без.png.materialрешает, как рисуются прозрачные пиксели:
| Материал | Пиксели | Подходит для |
|---|---|---|
particles_alpha | Либо полностью непрозрачные, либо полностью невидимые | Пиксель-арт, как ванильные сердечки и криты. Безопасный выбор. |
particles_blend | Могут быть полупрозрачными | Мягкий дым, туман, тающая пыль |
particles_add | Добавляются поверх того, что за ними, поэтому светятся | Магия, искры, огонь, свет |
Наша искра должна светиться, поэтому, когда всё заработает, смените материал на particles_add. Пока тестируете, начните с particles_alpha, его проще всего разглядеть.
Версия формата
1.10.0 - версия, которую использует большинство частиц в аддонах, и все компоненты на этих страницах с ней работают. Новые ванильные файлы используют более высокие версии, но для этого гайда они не нужны.
Шаг 3: эмиттер
Теперь заполните components. Сначала спавнер. Нам нужна одна быстрая вспышка из 12 искр, разбросанных вокруг небольшого шара:
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_rate_instant": {
"num_particles": 12
},
"minecraft:emitter_shape_sphere": {
"radius": 0.4,
"direction": "outwards"
},emitter_lifetime_onceзапускает эмиттер один раз и затем удаляет его.emitter_rate_instantсоздаёт все 12 частиц в один момент.emitter_shape_sphereразмещает их внутри шара радиусом 0.4 блока, и каждая смотрит от центра наружу.
Каждому эмиттеру нужен один компонент времени жизни и один компонент частоты. Без них ничего не появится. Форма необязательна: если её не указать, каждая частица начнёт точно из центра.
Шаг 4: частицы
Теперь расскажите каждой искре, как двигаться и выглядеть. Добавьте это после компонентов эмиттера:
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6, 1.2)"
},
"minecraft:particle_initial_speed": 1.5,
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 1.2, 0],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": [0.12, 0.12],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": [1, 0.15, 0.3, 1]
}Вот что делает каждый из них:
- Время жизни. Каждая искра живёт от 0.6 до 1.2 секунды.
math.randomвыбирает новое число для каждой частицы, поэтому они исчезают не все сразу. Это Molang, маленький математический язык Bedrock. - Скорость. Они вылетают со скоростью 1.5 блока в секунду в направлении, которое задала сфера.
- Движение.
linear_accelerationкаждую секунду немного подталкивает их вверх, и они парят, как угольки.linear_drag_coefficient- сопротивление воздуха: оно быстро гасит первый рывок. - Билборд. Каждая частица - плоский квадрат.
size- половина его ширины и высоты в блоках, так что0.12даёт квадрат шириной примерно в четверть блока.lookat_xyzдержит его повёрнутым к игроку. - UV. Выбирает, какую часть текстуры показывать. Наша текстура - одна картинка 8x8, поэтому берём её целиком: начинаем с
0, 0и берём8, 8. - Окрашивание. Красный, зелёный, синий и альфа, каждый от 0 до 1.
[1, 0.15, 0.3, 1]- это рубиново-красный. Можно также написать"#FF2650".
Сохраните, загрузите мир и введите:
/particle wiki:ruby_sparkle ~ ~1 ~Перед вами должно подняться маленькое красное облачко. Если ничего не видно, загляните в таблицу в конце этой страницы.
Шаг 5: заставьте её мерцать с помощью кривой
Сейчас каждая искра сохраняет один размер, пока внезапно не исчезнет. Это исправляет кривая. Это значение, которое следует форме, заданной несколькими числами.
Добавьте блок curves рядом с description и components:
"curves": {
"variable.ruby_size": {
"type": "linear",
"input": "variable.particle_age / variable.particle_lifetime",
"nodes": [0.2, 1, 0.6, 0]
}
},- Имя должно начинаться с
variable.. Игра вычисляет кривую для каждой частицы в каждом кадре и сохраняет результат в эту переменную. input- в каком месте кривой мы находимся. Возраст, делённый на время жизни, идёт от0(только родилась) до1(вот-вот исчезнет).nodes- значения по пути, равномерно распределённые от начала до конца. Наша искра начинается маленькой (0.2), вырастает до полного размера (1), уменьшается (0.6) и пропадает (0).type- как кривая идёт между узлами.linearрисует прямые линии.catmull_romиbezierделают плавные изгибы, аbezier_chainпозволяет самому задать каждую точку и наклон.
Теперь используйте переменную в размере билборда:
"size": ["0.12 * variable.ruby_size", "0.12 * variable.ruby_size"],Чтобы частица угасала, окрашивание тоже может менять цвет за время её жизни. gradient перечисляет цвета, а interpolant выбирает, где мы между ними:
"minecraft:particle_appearance_tinting": {
"color": {
"gradient": ["#FFFF8FA8", "#FFFF2650", "#00A0002A"],
"interpolant": "variable.particle_age / variable.particle_lifetime"
}
}Каждый цвет здесь записан как #AARRGGBB, то есть первые два символа - это альфа. Искра начинается бледно-розовой, становится рубиново-красной и заканчивается тёмной и невидимой. С particles_add тёмные цвета растворяются в ничто, и для светящихся эффектов это смотрится чудесно.
Шаг 6: добавьте хлопок с помощью события
События заставляют что-то происходить в определённый момент. Давайте оставлять крошечное облачко пыли там, где исчезает каждая искра.
Сначала сделайте пыль. Это второй, более мелкий эффект:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_dust",
"basic_render_parameters": {
"material": "particles_add",
"texture": "textures/particle/ruby_sparkle"
}
},
"components": {
"minecraft:emitter_lifetime_once": { "active_time": 0.2 },
"minecraft:emitter_rate_instant": { "num_particles": 3 },
"minecraft:emitter_shape_point": {},
"minecraft:particle_initial_speed": 0.4,
"minecraft:particle_lifetime_expression": { "max_lifetime": 0.3 },
"minecraft:particle_appearance_billboard": {
"size": [0.04, 0.04],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": { "color": "#FF7A0F2E" }
}
}
}Затем вернитесь в ruby_sparkle.json, дайте событию имя и скажите, что оно делает:
"events": {
"pop": {
"particle_effect": {
"effect": "wiki:ruby_dust",
"type": "emitter"
}
}
},И наконец, запускайте событие, когда у каждой искры заканчивается жизнь:
"minecraft:particle_lifetime_events": {
"expiration_event": "pop"
}Событие умеет не только создавать частицы:
| Поле события | Что делает |
|---|---|
particle_effect | Запускает другой эффект. type бывает emitter, emitter_bound, particle или particle_with_velocity |
sound_effect | Проигрывает звук по имени звукового события в event_name |
expression | Выполняет выражение Molang на эмиттере |
log | Пишет сообщение в журнал контента, удобно для тестов |
sequence | Список событий, которые выполняются все, одно за другим |
randomize | Список событий, из которых выполняется только одно, выбранное по weight |
Не давайте эффекту создавать самого себя
Если бы wiki:ruby_sparkle запускал wiki:ruby_sparkle из своего же события, каждая частица создавала бы новые частицы, и так бесконечно. Всегда направляйте события на другой, более мелкий эффект.
Готовый файл
Вот искра целиком, со включённым светящимся материалом:
{
"format_version": "1.10.0",
"particle_effect": {
"description": {
"identifier": "wiki:ruby_sparkle",
"basic_render_parameters": {
"material": "particles_add",
"texture": "textures/particle/ruby_sparkle"
}
},
"curves": {
"variable.ruby_size": {
"type": "linear",
"input": "variable.particle_age / variable.particle_lifetime",
"nodes": [0.2, 1, 0.6, 0]
}
},
"events": {
"pop": {
"particle_effect": {
"effect": "wiki:ruby_dust",
"type": "emitter"
}
}
},
"components": {
"minecraft:emitter_lifetime_once": {
"active_time": 0.5
},
"minecraft:emitter_rate_instant": {
"num_particles": 12
},
"minecraft:emitter_shape_sphere": {
"radius": 0.4,
"direction": "outwards"
},
"minecraft:particle_lifetime_expression": {
"max_lifetime": "math.random(0.6, 1.2)"
},
"minecraft:particle_lifetime_events": {
"expiration_event": "pop"
},
"minecraft:particle_initial_speed": 1.5,
"minecraft:particle_initial_spin": {
"rotation": "math.random(0, 360)",
"rotation_rate": 90
},
"minecraft:particle_motion_dynamic": {
"linear_acceleration": [0, 1.2, 0],
"linear_drag_coefficient": 3
},
"minecraft:particle_appearance_billboard": {
"size": ["0.12 * variable.ruby_size", "0.12 * variable.ruby_size"],
"facing_camera_mode": "lookat_xyz",
"uv": {
"texture_width": 8,
"texture_height": 8,
"uv": [0, 0],
"uv_size": [8, 8]
}
},
"minecraft:particle_appearance_tinting": {
"color": {
"gradient": ["#FFFF8FA8", "#FFFF2650", "#00A0002A"],
"interpolant": "variable.particle_age / variable.particle_lifetime"
}
}
}
}
}Мы ещё незаметно добавили particle_initial_spin: каждая искра начинает под случайным углом и медленно вращается, так что двух одинаковых не будет.
Как показать частицу
Командой
/particle проигрывает эффект в заданной точке. Для неё нужны включённые читы.
/particle wiki:ruby_sparkle ~ ~1 ~Её можно поставить и в функцию или командный блок. Чтобы показать её на ком-то, используйте execute: /execute as @a at @s run particle wiki:ruby_sparkle ~ ~2 ~ покажет искру над головой каждого игрока.
Из анимации моба
Моб может проигрывать частицы из своих анимаций. Это делается в файле клиентской сущности в пакете ресурсов, так что, если вы ещё не делали моба, сначала посмотрите Ваш первый моб.
1. Дайте эффекту короткое имя в description клиентской сущности:
"particle_effects": {
"sparkle": "wiki:ruby_sparkle"
}2. Запустите его из анимации в нужный момент времени. locator необязателен: это именованная точка на модели, и эффект следует за ней, пока моб двигается. Без него эффект появляется у ног моба.
"particle_effects": {
"0.5": {
"effect": "sparkle",
"locator": "head"
}
}3. Или запустите его из состояния контроллера анимаций. Он начнётся, когда моб войдёт в это состояние:
"particle_effects": [
{ "effect": "sparkle" }
]У каждого из них может быть pre_effect_script: немного Molang, который выполняется прямо перед стартом эффекта. С его помощью можно передать значения в файл частицы, например цвет, который зависит от моба.
Зацикленные эффекты - для мобов
Когда моб проигрывает эффект, эмиттер эффекта прикрепляется к нему. Вот где раскрываются emitter_lifetime_looping и emitter_lifetime_expression: след, который тянется за мобом, пока он идёт, или свечение, пока включено значение Molang.
Из скрипта
Скрипты могут показывать частицы где угодно и когда угодно. В манифесте пакета поведения нужен модуль скриптов: как его добавить, показано в разделе Настройка проекта.
import { world } from "@minecraft/server";
world.afterEvents.itemUse.subscribe(({ source, itemStack }) => {
if (itemStack.typeId !== "wiki:ruby_wand") return;
const { x, y, z } = source.location;
source.dimension.spawnParticle("wiki:ruby_sparkle", { x, y: y + 1.5, z });
});Каждый раз, когда игрок использует предмет wiki:ruby_wand, над ним вспыхивает искра. dimension.spawnParticle показывает эффект всем вокруг. player.spawnParticle работает так же, но видит его только этот игрок.
Ещё скрипты могут передавать значения в частицу через MolangVariableMap. Так один файл частицы может делать искры любого цвета:
import { MolangVariableMap } from "@minecraft/server";
// Inside the same itemUse handler as above:
const vars = new MolangVariableMap();
vars.setColorRGB("variable.tint", { red: 0.2, green: 0.6, blue: 1 });
source.dimension.spawnParticle("wiki:ruby_sparkle", { x, y: y + 1.5, z }, vars);В файле частицы читайте три части цвета как variable.tint.r, variable.tint.g и variable.tint.b:
"minecraft:particle_appearance_tinting": {
"color": ["variable.tint.r", "variable.tint.g", "variable.tint.b", 1]
}Полезные переменные Molang
Эти значения игра заполняет за вас. Используйте их в любом поле Molang.
| Переменная | Значение |
|---|---|
variable.particle_age | Сколько секунд эта частица уже живёт |
variable.particle_lifetime | Сколько всего проживёт эта частица |
variable.particle_random_1 до _4 | Четыре случайных числа от 0 до 1, свои у каждой частицы |
variable.emitter_age | Сколько уже работает эмиттер |
variable.emitter_lifetime | Сколько всего работает эмиттер |
variable.emitter_random_1 до _4 | Четыре случайных числа от 0 до 1, общие для всего эмиттера |
variable.entity_scale | Размер моба, к которому прикреплён эффект |
variable.particle_random_1 отлично подходит для разнообразия. Например, "0.1 + variable.particle_random_1 * 0.05" даёт каждой искре чуть другой размер.
Если что-то не работает
| Что вы видите | Самая вероятная причина |
|---|---|
| Вообще ничего | У эмиттера нет компонента времени жизни или частоты, или identifier в команде не совпадает с файлом |
/particle пишет, что эффекта не существует | Опечатка в JSON. Откройте журнал контента, чтобы найти сломанную строку |
| Фиолетово-чёрный квадрат | Неверный путь texture, или он заканчивается на .png |
| Вся текстура сжата в одну частицу | Нет блока uv, или texture_width и texture_height не совпадают с PNG |
| Чёрные квадраты вокруг каждой частицы | Фон PNG не прозрачный, или вы использовали particles_add с тёмной картинкой |
| Частица не того цвета | Окрашивание умножает текстуру. Рисуйте текстуру белым |
| Она никогда не заканчивается | Используется emitter_lifetime_looping. Для разовой вспышки используйте emitter_lifetime_once |
Больше помощи в разделе Когда что-то сломалось. Хотите больше? Все настройки эмиттера есть на странице Компоненты эмиттера, а все настройки частиц на странице Компоненты частиц.