Cette page n’est pas encore traduite : la version anglaise est affichée.
Le schéma dans le code
Déclarez le modèle dans le code, publiez-le, récupérez les types. C’est ainsi que le développeur travaille avec le schéma : le panneau d’administration et le code décrivent le même modèle, et la génération de code boucle la boucle pour chaque moteur.
Quand l’utiliser
- Votre modèle de données doit vivre dans le code et être relu comme du code : déclarer,
schema diff,schema push. - Les types du moteur ne doivent jamais s’écarter du modèle déployé :
schema codegenrégénère le code Unreal C++ et Unity C#. - Un changement incompatible doit pouvoir être lu, et annulé, avant de s’exécuter : proposer → planifier → appliquer.
- Vous réutilisez le même ensemble (
Stat,Interactable) d’un projet à l’autre : déclarez-le une fois comme preset. - Inutile si un opérateur se contente d’ajuster des valeurs dans le panneau d’administration. La modification du modèle revient quand même dans le code par le diff.
Qui fait quoi
| Acteur | Ce qu’il fait sur cette page |
|---|---|
schema-author | déclare dans le code les entités, les parties et les énumérations, les compare au modèle déployé et les publie |
operator | consulte la vue d’ensemble dans le panneau, propose et applique les migrations |
ci | le pipeline de build, qui tourne avec une clé backend-service : il publie le schéma à chaque merge, puis régénère les types des moteurs |
En bref
Item avec une partie Stats intégrée et une énumération, publiés en un seul schéma[Entity("item")]
public class Item
{
public string Name = "";
public Rarity Rarity; // an enum declared the same way
public Stats Stats = new(); // a part — embedded, no lifecycle of its own
}
[Part("stats")]
public class Stats { public int Power; public int Weight; }@Entity('item')
export class Item {
name = '';
rarity!: Rarity; // an enum declared the same way
stats = new Stats(); // a part — embedded, no lifecycle of its own
}
@Part('stats')
export class Stats { power = 0; weight = 0; }@entity("item")
class Item:
name: str = ""
rarity: Rarity # an enum declared the same way
stats: Stats = Stats() # a part — embedded, no lifecycle of its own
@part("stats")
class Stats:
power: int = 0
weight: int = 0La déclaration par attributs en Go n’est pas encore tranchée (O-1). Les exemples arriveront quand la forme d’écriture sera choisie.
USTRUCT(PSPart = "stats")
struct FItemStats
{
GENERATED_BODY()
UPROPERTY() int32 Power;
UPROPERTY() int32 Weight;
};
UCLASS(PSEntity = "item")
class UItem : public UObject
{
GENERATED_BODY()
UPROPERTY() FString Name;
UPROPERTY() EPSRarity Rarity; // an enum declared the same way
UPROPERTY() FItemStats Stats; // a part — embedded, no lifecycle of its own
};
// declarations compile into the same pushed model — playserv push from the UE project or CI[Entity("item")]
public class Item
{
public string Name = "";
public Rarity Rarity; // an enum declared the same way
public Stats Stats = new(); // a part — embedded, no lifecycle of its own
}
[Part("stats")]
public class Stats { public int Power; public int Weight; }playserv schema diff # local declarations vs deployed schema
playserv schema push # with a revision precondition — no blind overwrites
playserv schema codegen # regenerate Unreal C++ / Unity C# types
La publication est une étape explicite
Enregistrer un fichier n’envoie rien. Une déclaration n’atteint le modèle déployé que lorsque playserv push (ou schema push) s’exécute, sur votre machine ou dans la CI, et elle emporte la révision par rapport à laquelle le diff a été calculé. Une modification faite dans le panneau apparaît comme un écart dans schema diff. Dans un sens comme dans l’autre, faire passer un changement reste toujours une commande que vous lancez vous-même.
Le modèle
Ce que contient une déclaration.
| Contient | Ce que c’est |
|---|---|
key | le nom stable par lequel on la désigne. Renommer dans le code reste un renommage, pas une suppression suivie d’une création |
kind | une entité, une partie ou une énumération, déclarée dans le code |
mode de propriété | seed — le code crée l’enregistrement s’il n’existe pas, et une nouvelle publication ne touche pas aux valeurs : la console d’administration en devient ensuite propriétaire. Ou managed — le code en reste toujours propriétaire, chaque publication ramène les valeurs à ce qui est déclaré, et les modifications venant de la console d’administration sont refusées plutôt qu’appliquées puis perdues à la publication suivante |
preset | facultatif : un ensemble réutilisable — un preset d’entité comme stats ou world-objects — déclaré une fois et appliqué comme un type. Il n’introduit aucune nouvelle sorte de déclaration |
Ce que garantit une publication.
| Toujours | Ce que c’est |
|---|---|
correspondance | se fait par clé, jamais par symbole : si vous renommez le symbole puis publiez à nouveau, il reste un seul enregistrement, pas deux |
le rapport | indique exactement ce qui va changer avant l’application, puis ce qui a été écrasé |
origine | reste identifiable : un enregistrement créé par une publication depuis le code se distingue de celui créé ailleurs |
la révision | accompagne la publication, qui s’applique en entier ou pas du tout |
Ce que garantit la génération de code.
| Toujours | Ce que c’est |
|---|---|
régénération | a lieu après chaque publication, et on ne modifie jamais à la main les types générés : régénérer puis comparer ne produit aucune différence |
nommage | suit la déclaration, où qu’elle ait été écrite — le champ Rarity de Item devient UPSItem::Rarity dans Unreal et Item.Rarity dans Unity |
les deux sens | ne divergent pas : tout ce qui est déclaré dans le code apparaît dans le panneau, et tout ce qu’un opérateur crée dans le panneau se compare proprement au code. schema diff montre donc chaque différence |
Ce que garantit une migration.
| Toujours | Ce que c’est |
|---|---|
quand elle est nécessaire | lorsqu’une déclaration persistante change et que ce changement réécrit des valeurs existantes |
ce qu'elle déclare | une version, un aperçu, une application ordonnée, un rollback en cas d’échec et un résultat final observable |
coexistence | tant que deux versions des données sont actives, les lectures et les écritures déclarent quelles versions elles acceptent — le runtime ne déduit jamais la compatibilité des noms de champs |
Erreurs
- Un appelant sans le rôle reçoit
forbidden, et le modèle déployé reste intact : un refus n’est jamais une publication partielle. Ce refus diffère de celui d’une révision périmée, qui renvoieprecondition_failed: le diff a été calculé par rapport à un schéma qui a changé depuis. Recalculez le diff et publiez à nouveau. - Une valeur hors des bornes déclarées est refusée à l’écriture, jamais ramenée dans l’intervalle, tout comme une chaîne qui dépasse sa longueur déclarée. La borner donnerait une valeur valide, mais fausse.
- Une séquence UTF-8 invalide est rejetée à l’écriture, pas réparée.
- Un changement persistant incompatible sans migration déclarée ne peut tout simplement pas être publié.
Limites
Les plafonds liés à la déclaration sont vérifiés au moment de la déclaration — au déploiement ou à la publication — plutôt qu’à la première utilisation, partout où le symptôme à l’exécution ne ressemblerait pas à un refus. Les valeurs chiffrées arriveront avec le chapitre sur les limites de la plateforme.