Цю сторінку ще не перекладено — показано англійську версію.
Entity presets
Пресет — це іменований набір аспектів сутності — даних, станів, RPC, подій, хуків, — зібраний під один ігро вий сценарій. Пресет можна застосувати, підлаштувати його числа або вивести з нього власний. Застосований пресет додає аспекти до вашого типу, але не ставить ваш тип нижче за щось в ієрархії: пресет — не модуль, і успадковувати в ньому нічого. Характеристики, здібності, снаряди, таблиці випадання та об’єкти світу — це п’ять пресетів, а не п’ять підсистем: те саме оголошення, та сама синхронізація, той самий порядок хуків.
Коли це потрібно
- У вашій грі є об’єкт із числами, які не виходять за межі, відновлюються й запускають перехід, коли досягають межі.
- Дії потрібні вартість, перезаряджання (cooldown), фази та ефекти, і клієнт має запускати її однією командою.
- Щось летить, і влучання треба чесно оцінити навіть для стрільця з лагом.
- Здобич має випадати за зваженими шансами, які точно відтворюються, коли гравець оскаржує випадання.
- На мапі є обладнання — двері, кнопки, пастки, руйновані об’єкти, — стани якого мають зберегтися, коли гравець приєднується посеред раунду.
- Пресети не потрібні, коли сутність (entity) — це просто синхронізовані дані. Оголосіть поля, і цього досить.
Хто що робить
| Актор | Що робить на цій сторінці |
|---|---|
schema-author | оголошує характеристики, здібності, снаряди, таблиці випадання, об’єкти світу |
room-owner | налаштовує числа пресетів, кидає жереб за таблицями випадання, створює об’єкти світу |
player | застосовує здібності, стріляє, підбирає здобич, взаємодіє з об’єктами |
Коротко
Crate з двох готових пресетів, потім створюємо ящик одним рядком і налаштовуємо його на 250 HP// derived once, in the schema
[Entity("crate", Persistence = Persistence.Runtime, Presets = new[] { Preset.WorldObjects, Preset.Stats })]
public class Crate { [Stat(Max = 100, AtMin = "broken")] public Stat Hp; }
// then one line per crate, on the room host
var crate = await room.Create<Crate>(at: pos, tune: c => c.Hp.Max = 250);// derived once, in the schema
@Entity('crate', { persistence: Persistence.Runtime, presets: [Preset.WorldObjects, Preset.Stats] })
export class Crate { @Stat({ max: 100, atMin: 'broken' }) hp: Stat; }
// then one line per crate, on the room host
const crate = await room.create<Crate>({ at: pos, tune: (c) => { c.hp.max = 250; } });# derived once, in the schema
@entity("crate", persistence=Persistence.RUNTIME, presets=[Preset.WORLD_OBJECTS, Preset.STATS])
class Crate:
hp = stat(max=100, at_min="broken")
# then one line per crate, on the room host
crate = await room.create(Crate, at=pos, tune={"hp.max": 250})Як оголошувати через атрибути в Go, поки не вирішено (O-1). Приклади з’являться, коли оберуть спосіб запису.
// declarations compile into the same pushed model — playserv push from the UE project or CI
UCLASS(PSEntity = (Name = "crate", Persistence = "Runtime", Presets = "world-objects, stats"))
class UCrate : public UObject
{
GENERATED_BODY()
UPROPERTY(PSStat = (Max = 100, AtMin = "broken")) FPSStat Hp;
};
// then one line per crate, on the room host (dedicated server / master-client)
Room->Entities->Of<UCrate>()->Create(FPSIdempotencyKey(CrateId),
[SpawnPosition](UCrate& Crate) { Crate.Position = SpawnPosition; }); // Position — from the world-objects preset
// co_await support ships later: a built-in SDK coroutine wrapper that respects Unreal's GC and threading.// derived once, in the schema
[Entity("crate", Persistence = Persistence.Runtime, Presets = new[] { Preset.WorldObjects, Preset.Stats })]
public class Crate { [Stat(Max = 100, AtMin = "broken")] public Stat Hp; }
// then one line per crate, on the room host
var crate = await room.Create<Crate>(at: pos, tune: c => c.Hp.Max = 250);Модель
Пресет не вводить нових понять. Усе, що він додає, можна виразити засобами, які вже дає сутність: аспектами, машинами станів, хуками, зберіганням.
Що дає кожен пресет і де його налаштовують.
| Пресет | Що дає йому контракт | Де налаштовують |
|---|---|---|
stats | аспект числових характеристик (stat) з межами, відновленням і модифікаторами, а також хук на досягнення порога: 0 HP стає переходом машини станів, а не if у вашому коді | оголошення (declaration) поля; числа можна змінювати наживо в панелі |
abilities | аспект із набором здібностей (ability), машина фаз застосування, вартість і п ерезаряджання | оголошення здібності |
projectiles | тип із режимом зберігання runtime, аспект балістики й подія (event) влучання | оголошення снаряда: заміна одного атрибута змінює модель польоту |
drops | аспект таблиці випадання (drop table) з вагами і хук після смерті | записи таблиці та їхні ваги |
world objects | машина станів (state machine) інтерактивного об’єкта й аспект умови взаємодії | оголошення пресета або кожен екземпляр окремо під час створення |
| inventory | тип із власником, який тримає ref на предмет каталогу (catalog), аспект стосу з інкрементом і ліміт на власника з оголошеною поведінкою при переповненні | оголошення типу |
В Inventory є й окрема сторінка.
Що справджується для кожного пресета.
| Завжди | Що це |
|---|---|
де він живе | на сутності, у вигляді аспектів: його дані синхронізуються, як будь-які інші дані, його стани — це стани сутності, його RPC — це RPC сутності, а його хуки виконуються в порядку хуків сутності |
налаштування | це жива конфігурація, а не повторний деплой. Тому панель показує межу характеристики, перезаряджання й вагу випадання в одному дереві |
власний пресет | виводять композицією, а не успадкуванням: Crate — це world-objects плюс stats, і результат однаково лишається аспектами на сутності |
Помилки
- Оголосити характеристику, здібність, снаряд, таблицю випадання чи об’єкт світу означає змінити схему (schema), тому потрібен
fnабоadm. Якщо таке оголошення спробує зробити ключ гравця чи клієнта, він отримаєforbidden, і нічого не буде оголошено ні повністю, ні наполовину. Це інша відмова, ніж ті, що трапляються гравцеві всередині виклику, який йому дозволено зробити: перезаряджання ще триває, нема чим заплатити, бракуєitem:key.bronze. Кожна з них має власний код.
Решта відмов пресета — це відмови сутності. Дві стосуються саме пресетів:
- Частково заповнений пресет не проходить валідацію під час деплою. Пресет містить узгоджений набір: половину оголошення платформа відхиляє ще до випуску, а не дає їй дивно поводитися в матчі.
- Пресет не можна позначити властивістю, яка суперечить його власній механіці. Наприклад, аспект, для якого в клієнта немає правил, не можна оголосити передбачуваним, і це теж виявляється під час деплою.
Обмеження
Стелі тут ті самі, що й у сутності: кількість аспектів і машин станів на тип, розмір збереженого екземпляра, частота змін одного екземпляра. Сам пресет оголошує лише ліміт на власника, який несе пресет із власником. Він має одну з трьох по ведінок на межі й не має значення за замовчуванням: refuse · redirect в оголошений кошик власника · discard with event. Конкретні числа з’являться разом із розділом про ліміти платформи.