Microsoft Foundry a Foundry Local: Kde by měla běžet vaše AI aplikace?
Jak může vypadat vývoj aplikací nad modely, které běží v cloudu a na lokálním zařízení.
Přejít na obsah|Přejít k hlavnímu menu|Přejít k vyhledávání
Přechod od klasického programování k vývoji her neznamená zahodit dosavadní znalosti a začít od začátku. Algoritmy, datové struktury, práce se stavem, testování nebo správa závislostí zůstávají důležité. Mění se však způsob, jakým o programu přemýšlíme: hra musí reagovat v reálném čase, udržovat konzistentní svět a koordinovat logiku, fyziku, animace, grafiku i zvuk.
Zatímco běžná aplikace často čeká na konkrétní událost — například odeslání formuláře nebo požadavek na server — herní aplikace svůj stav aktualizuje nepřetržitě. Herní programátor proto neřeší pouze správnost výsledku, ale také jeho načasování, stabilitu snímkové frekvence, životní cyklus objektů a spolupráci několika systémů současně.
Hlavním cílem tohoto článku je vysvětlit právě tento přechod: co si lze z klasického programování přenést, jaké nové principy je nutné osvojit a jak do práce zapadá herní engine. Praktický kontext vychází z vývoje 2D adventury a plošinovky s jednoduchým soubojovým systémem, kterou v enginu Godot vytvářel čtyřčlenný tým složený ze dvou programátorů, grafičky a audio developera.
Vedle základů herní architektury článek porovnává enginy Godot, Unity a Unreal Engine, věnuje se využití umělé inteligence a ukazuje, proč je pro řízení návrhu důležitý Game Design Document.
Základní principy programování zůstávají stejné bez ohledu na typ aplikace. Herní vývoj stále pracuje s algoritmy, datovými strukturami, objektovým nebo funkcionálním návrhem, testováním, správou paměti a verzováním zdrojového kódu.
Rozdíl spočívá především v provozních požadavcích a v charakteru výsledného systému.
Běžná aplikace může pracovat například takto:
Videohra naproti tomu musí svůj stav aktualizovat nepřetržitě. Když hra běží:
Při cílových 60 snímcích za sekundu má aplikace na vytvoření jednoho snímku přibližně 16,67 ms. Do tohoto časového rozpočtu se musí vejít všechny systémy, které jsou pro daný snímek potřeba.
V klasické aplikaci může být přirozené objekt vytvořit, použít a následně odstranit. Ve hře se však některé objekty vytvářejí velmi často — například projektily, částice, nepřátelé nebo zvukové zdroje.
Naivní přístup může vypadat následovně:
Projectile projectile = Instantiate(projectilePrefab);
projectile.Initialize(position, direction);
Destroy(projectile.gameObject, 3f);Takové řešení je jednoduché a pro malý počet objektů může být zcela dostačující. Při vysoké frekvenci vytváření a odstraňování však může způsobovat zbytečné alokace, práci garbage collectoru a kolísání výkonu.
Alternativou je object pooling:
Projectile projectile = projectilePool.Get();
projectile.Activate(position, direction);
// Po zásahu nebo vypršení životnosti:
projectilePool.Release(projectile);Objekt není fyzicky odstraněn. Deaktivuje se, vrátí do zásobníku a později se znovu použije.
Zkušenost z praxe: Object pooling není automaticky správnou volbou pro každý objekt. Přináší složitější správu stavu a vyžaduje důsledný reset všech hodnot, událostí, animací a fyzikálních parametrů.

Game loop je hlavní řídicí smyčka hry. Koordinuje zpracování vstupů, herní logiku, fyziku a vykreslování.
Zjednodušená implementace může vypadat takto:
while (isRunning)
{
ProcessInput();
UpdateGame(deltaTime);
SimulatePhysics(fixedDeltaTime);
Render();
}V moderních enginech hlavní smyčku obvykle nepíšeme ručně. Engine ji provozuje za nás a volá připravené metody, události nebo callbacky.
Herní programátor přesto musí rozumět tomu, kdy se jednotlivé části kódu spouštějí. Chybně umístěná logika může vést například k nestabilní fyzice, zpožděnému vstupu nebo rozdílnému chování na různě výkonných zařízeních.

Pohyb objektu by neměl být přímo závislý na počtu vykreslených snímků.
position.x += speed;Pokud se tento kód spustí jednou za snímek, bude se objekt při 120 FPS pohybovat přibližně dvakrát rychleji než při 60 FPS.
position.x += speed * deltaTime;Proměnná deltaTime reprezentuje čas, který uplynul od předchozí aktualizace. Díky tomu lze rychlost vyjádřit například v metrech nebo pixelech za sekundu.
Důležité: Fyzika bývá aktualizována v pevném časovém kroku. Vstup, animace a vizuální logika mohou používat jinou frekvenci. Tyto režimy není vhodné bez rozmyslu zaměňovat.
Při čistě dědičném návrhu může postupně vzniknout obtížně udržovatelná hierarchie:
GameObject
└── Character
└── Enemy
└── FlyingEnemy
└── ArmoredFlyingEnemy
Komponentový přístup skládá herní objekt z menších, opakovaně použitelných schopností:
Enemy
├── HealthComponent
├── MovementComponent
├── AttackComponent
├── InventoryComponent
└── AIController
Tento přístup má několik praktických výhod:
State machine neboli stavový automat je vhodný pro systémy, které se mohou nacházet v jednom z několika jasně definovaných stavů.
Příklad chování nepřítele:
Idle → Patrol → Chase → Attack
↓
Dead
Pro menší systém je switch přehledný a efektivní. U složitější logiky je vhodné jednotlivé stavy rozdělit do samostatných tříd, uzlů nebo datově řízených konfigurací.
Object pool uchovává předem vytvořené objekty a opakovaně je používá.
Při vrácení herního objektu do poolu je nutné obnovit jeho výchozí stav. Typicky se resetuje:
Praktické pravidlo: Pooling používejte tam, kde měření skutečně ukáže časté vytváření objektů nebo nestabilní dobu snímku. Optimalizace bez měření často pouze zvyšuje složitost.

Herní engine je soubor nástrojů a runtime systémů, které řeší opakující se části vývoje. Typicky poskytuje:
Herní engine neodstraňuje potřebu programování. Odstraňuje potřebu opakovaně vytvářet technologický základ, který většina her potřebuje (Godot, Unity, Unreal Engine atd.).
Godot používá strom scén a uzlů. Každý uzel reprezentuje konkrétní schopnost nebo část objektu — například obraz, fyzikální těleso, kameru, animaci či zvukový přehrávač.
Nejčastěji používané jazyky:
Godot je vydáván pod permisivní licencí MIT. Engine lze používat, upravovat a distribuovat i v komerčních projektech; při distribuci je nutné zachovat příslušné licenční oznámení. Pro malý tým je výhodou také možnost používat engine bez licenčních poplatků odvozených od příjmů hry.
Unity staví na objektech GameObject a komponentách. Primárním programovacím jazykem je C#.
Unity nabízí bezplatný plán Personal pro jednotlivce a menší organizace, které splňují aktuální finanční limit. K červenci 2026 je hranice stanovena na 200 000 USD příjmů a získaného financování za posledních 12 měsíců. Plán Unity Pro stojí v roce 2026 při roční platbě 2 310 USD za jedno pracovní místo. Konkrétní podmínky je vhodné ověřit podle velikosti firmy, cílových platforem a způsobu distribuce.
Unreal Engine používá kombinaci C++ a vizuálního skriptování Blueprints. Je známý především výkonnými nástroji pro 3D rendering, animaci, filmovou tvorbu a rozsáhlá prostředí.
Pro hry a další produkty, které používají kód Unreal Enginu za běhu a jsou distribuovány koncovým uživatelům, se standardně uplatňuje pětiprocentní licenční poplatek z části celoživotních hrubých příjmů produktu přesahující jeden milion USD. Příjmy z prodeje v Epic Games Store jsou podle aktuálních podmínek od tohoto poplatku osvobozeny.
Pro srovnání použijeme jednoduchý pohyb postavy. Ukázky nejsou dokonale rovnocenné, protože každý engine pracuje s jiným objektovým modelem a poskytuje jinou úroveň vestavěné funkcionality.
extends CharacterBody2D
@export var speed: float = 250.0
func _physics_process(delta: float) -> void:
var direction := Input.get_vector(
"move_left",
"move_right",
"move_up",
"move_down"
)
velocity = direction * speed
move_and_slide()Godot poskytuje metodu _physics_process(), která je určena pro fyzikální aktualizace. Vstupní akce se definují v nastavení projektu.
using UnityEngine;
[RequireComponent(typeof(Rigidbody2D))]
public sealed class PlayerMovement : MonoBehaviour
{
[SerializeField] private float speed = 5f;
private Rigidbody2D body;
private Vector2 input;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
input = new Vector2(
Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")
).normalized;
}
private void FixedUpdate()
{
body.linearVelocity = input * speed;
}
}Unity zde odděluje čtení vstupu v metodě Update() a aplikaci fyzikální rychlosti v FixedUpdate().
void APlayerCharacter::Move(const FVector2D& InputValue)
{
if (!Controller)
{
return;
}
const FRotator Rotation = Controller->GetControlRotation();
const FRotator YawRotation(0.0f, Rotation.Yaw, 0.0f);
const FVector Forward =
FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
const FVector Right =
FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
AddMovementInput(Forward, InputValue.Y);
AddMovementInput(Right, InputValue.X);
}Unreal Engine používá robustnější charakterový a vstupní systém. Delší kód je vyvážen integrací s dalšími částmi enginu, jako jsou Character Movement Component, síťová replikace nebo root motion.
V další části tohoto seriálu se podíváme na srovnání jednotlivých enginů, nikoliv dle jejich popularity, ale vhodnosti na konkrétní projekty.
Jak může vypadat vývoj aplikací nad modely, které běží v cloudu a na lokálním zařízení.

Umělá inteligence nám pomáhá pracovat rychleji, efektivněji a s menší námahou. Její používání má však i svá úskalí. Pokud ji využíváme ve velké míře nebo na ni přenášíme stále více úkolů a necháme ji přemýšlet za nás, může se stát, že postupně dochází k oslabování dovedností, které jsme dříve při práci běžně využívali.

Zastaralý kód, v mnoha ohledech špatně napsaný. Původní autoři již v dané firmě nepracují. Dokumentace? Neexistující. Zní to jako úvod z hororu? Je však poměrně běžné, že naši zákazníci mají nějakou nedokumentovanou aplikaci, o které už pořádně nikdo nic neví, ale přitom ji potřebují spravovat. A přesně to je úkol pro nás.
Děkujeme za váš zájem o odběr našeho newsletteru! Pro dokončení registrace je potřeba potvrdit vaše přihlášení. Na zadaný e-mail jsme vám právě zaslali potvrzovací odkaz. Klikněte prosím na tento odkaz, aby bylo vaše přihlášení dokončeno. Pokud e-mail nenajdete, zkontrolujte prosím složku nevyžádané pošty (spam) nebo složku hromadné pošty.
