Цю сторінку ще не перекладено — показано англійську версію.
Аптечки в Tanks
Це другий урок на Tanks. У ньому три кроки й жодного нового модуля: оголошення (declaration) аптечки, оголошення місць, де з’являються аптечки, і один хук, який визначає, що дає підібрана аптечка. Проходьте його після сторінки Перші кроки — до чи після уроку про таблицю лідерів, неважливо.
Оголосіть аптечку
Аптечка — це сутність (entity) із застосованим пресетом об’єктів світу і тілом, яке повідомляє про дотик, але нікого не зупиняє. Саме Response.Pass на шарі pickups робить її предметом для підбору, а не перешкодою: платформа повідомляє про дотик, а рух проходить крізь аптечку без змін.
pickups — дотик реєструється, рух не змінюється[Entity("health-crate", Persistence = Persistence.Runtime, Presets = new[] { Preset.WorldObjects })]
public class HealthCrate
{
[Sync] public Vector3 Position;
[Body(Shape.Sphere, Radius = 0.5f, Layer = "pickups")]
[CollidesWith("vehicles", Response.Pass)] // reported, motion passes through
public Body Body;
}@Entity('health-crate', { persistence: Persistence.Runtime, presets: [Preset.WorldObjects] })
export class HealthCrate {
@Sync position: Vector3;
@Body({ shape: 'sphere', radius: 0.5, layer: 'pickups' })
@CollidesWith('vehicles', Response.Pass) // reported, motion passes through
body: Body;
}@entity("health-crate", persistence=Persistence.RUNTIME, presets=[Preset.WORLD_OBJECTS])
class HealthCrate:
position: Vector3 = sync()
body: Body = body(shape="sphere", radius=0.5, layer="pickups",
collides_with=[("vehicles", Response.PASS)])Як оголошувати через атрибути в Go, поки не вирішено (O-1). Приклади з’являться, коли оберуть спос іб запису.
UCLASS(PSEntity = (Name = "health-crate", Persistence = "Runtime", Presets = "world-objects"))
class UHealthCrate : public UObject
{
GENERATED_BODY()
UPROPERTY(PSSync) FVector3f Position;
UPROPERTY(PSBody = (Shape = "Sphere", Radius = "0.5", Layer = "pickups"),
PSCollidesWith = "vehicles:Pass") // reported, motion passes through
FPSBody Body;
};
// declarations compile into the same pushed model — playserv push from the UE project or CIОголошення пишуть у серверному проєкті й завантажують командою playserv push. Біндинг Unity на клієнті працює зі згенерованим типізованим інтерфейсом (HealthCrate).
Двох речей писати не довелося. Перша — де малювати аптечку: клієнт уже рендерит ь оголошені об’єкти світу (world objects). Друга — як її позиція потрапляє до клієнтів: [Sync] і є мережевим викликом.
Докладно — на сторінках Entity Presets і Collision.
Оголосіть, де з’являються аптечки
Розміщення — теж оголошення, і саме цей крок вирішує, чи здаватиметься механіка чесною. Відстань між аптечками не дає їм збиватися в купу, відстань від гравців (player) не дає їм з’являтися посеред дуелі, а правило без повторів не дає щоразу обирати ту саму точку.
[DropTable("health-crates", Layer = "ground", MinSpacing = 8, AwayFromPlayers = 10, NoRepeat = 3)]
public static partial class HealthCrates
{
public static readonly Drop Crate = Drop.Of<HealthCrate>(weight: 1);
}@DropTable('health-crates', { layer: 'ground', minSpacing: 8, awayFromPlayers: 10, noRepeat: 3 })
export class HealthCrates {
static crate = Drop.of(HealthCrate, { weight: 1 });
}@drop_table("health-crates", layer="ground", min_spacing=8, away_from_players=10, no_repeat=3)
class HealthCrates:
crate = drop_of(HealthCrate, weight=1)Як оголошувати через атрибути в Go, поки не вирішено (O-1). Приклади з’являться, коли оберуть спосіб запису.
USTRUCT(PSDropTable = (Name = "health-crates", Layer = "ground", MinSpacing = 8,
AwayFromPlayers = 10, NoRepeat = 3))
struct FHealthCrates
{
GENERATED_BODY()
UPROPERTY(PSEntry = (Entity = "health-crate", Weight = 1)) FPSDrop Crate;
};
// declarations compile into the same pushed model — playserv push from the UE project or CIОголошення пишуть у серверному проєкті й завантажують командою playserv push. Клієнт на Unity бачить результат як предмети, що з’явилися у світі, і події підбору.
Допустимі позиції дає Map. Таблиця випадання (drop table) просить точку на шарі ground, а мапа повертає таку, до якої справді можна дістатися, тож аптечка ніколи не опиниться всередині стіни.
Докладно — на сторінках Entity Presets і Map.
Лікування під час підбору
Один хук — і це єдиний код в уроці. Він працює на платформі як хмарна функція, тому його немає на жодній вкладці рушіїв.
[Before(Drops.Pickup)]
public static Verdict HealOnPickup(PickupIntent p)
{
if (p.WorldItem.Kind != "health-crate") return Hook.Continue(p);
if (p.Player.Tank.Hp.IsFull) return Hook.Reject("already at full health");
p.Player.Tank.Hp.Adjust(+40, by: p.Player);
return Hook.Continue(p);
}export const healOnPickup = before(Drops.pickup, (p: PickupIntent) => {
if (p.worldItem.kind !== 'health-crate') return Hook.continue(p);
if (p.player.tank.hp.isFull) return Hook.reject('already at full health');
p.player.tank.hp.adjust(+40, { by: p.player });
return Hook.continue(p);
});@before(drops.pickup)
def heal_on_pickup(p: PickupIntent) -> Verdict:
if p.world_item.kind != "health-crate":
return Hook.continue_(p)
if p.player.tank.hp.is_full:
return Hook.reject("already at full health")
p.player.tank.hp.adjust(+40, by=p.player)
return Hook.continue_(p)Як оголошувати через атрибути в Go, поки не вирішено (O-1). Приклади з’являться, коли оберуть спосіб запису.
Хук — це хмарна функція: він працює на платформі, а не в рушії. Напишіть його на C#, TypeScript або Python, а Unreal підпишеться на події зміни характеристики й підбору, які він породжує. У планах — функції, написані в самому рушії: графи Blueprint і C++ (його транслюватимуть у скрипт, який перевіряє платформа). Їх аналізуватимуть і завантажуватимуть, як будь-яке оголошення, а виконувати їх і далі буде платформа.
Хук — це хмарна функція: він працює на платформі, а не в рушії. Напишіть його на C#, TypeScript або Python, а Unity підпишеться на події зміни характеристики й підбору, які він п ороджує.
Чого хукові робити не потрібно:
- Відмова типізована. Танк із повним здоров’ям отримує
already at full healthіз причиною, яку клієнт може показати гравцеві, а аптечка лишається на місці для того, кому вона потрібніша. - Характеристики змінює лише сервер. Клієнт не може попросити змінити характеристику (stat), тож писати для підбору виняток в античиті не треба.
- HUD оновлюється сам.
Adjustпороджуєchanged, а клієнт уже підписаний на оголошені характеристики танка. Мережевого повідомлення ви не писали.
Докладно — на сторінках Extensibility і Entity Presets.
Що далі
- Entity Presets — генератор випадання, об’єкти світу і модель характеристик, на які спирався цей урок. Усі три — пресети
entity, а не модулі. - Collision — шари, реакції і різниця між дотиком, про який лише повідомляють, і дотиком, що зупиняє рух.
- Map — як обирають допустиму позицію і що означає «досяжна».
- Extensibility — усі точки виклику хуків по порядку і правила вето.
- Таблиця лідерів у Tanks — другий приклад на Tanks.