Files
PythonInUnreal/docs/animation_catalog.md
T
2026-10-31 23:11:57 +01:00

182 lines
7.4 KiB
Markdown

# Nazwy i długości animacji w VS Code
W `ue_workshop.animations` są statycznie zapisane enumy `FighterAnimations` i
`CreatureAnimations`. Działają w zwykłym Pythonie, bez `unreal`. Po wpisaniu kropki
VS Code może podpowiedzieć wszystkie klipy. Opisy członków podają długość w sekundach.
Nazwy odpowiadają nazwom plików; nie ma skrótów typu `attack`.
```python
from ue_workshop.animations import FighterAnimations, CreatureAnimations
draw = FighterAnimations.DRAW_A_GREAT_SWORD_1
attack = FighterAnimations.GREAT_SWORD_ATTACK
draw.key # "draw_a_great_sword_1"
draw.seconds # 0.5 sekundy
draw.frames(24) # 12 klatek przy 24 FPS
attack.seconds # około 1.2 sekundy
attack.frames(24) # 29 klatek przy 24 FPS, zaokrąglone w górę
attack.frames(24, speed=2)
# Bez end klip wybrany enumem gra raz, z automatycznie policzonym końcem.
shot.animation(character_fighter, draw, start=0)
next_start = draw.frames(shot.fps) - 6
shot.animation(character_fighter, attack, start=next_start)
```
W tym przykładzie przejście trwa 6 wspólnych klatek. Przy zmianie klipu albo FPS
nie trzeba pamiętać jego długości. `speed` jest uwzględniane zarówno przez `frames`,
jak i przez automatyczny koniec w `shot.animation`.
Podanie `end` nadal ustawia własny zakres i pozwala zapętlić klip:
```python
shot.animation(character_fighter, FighterAnimations.GREAT_SWORD_IDLE, start=0, end=120)
```
Dotychczasowe nazwy tekstowe nadal działają. Dla tekstu lub bez wskazania klipu
pominięte `end` zachowuje dotychczasowe znaczenie: gra do końca sekwencji.
Koniec sekcji musi mieścić się w `Sequence(..., frames=...)`.
## Zachowanie pozycji po ataku
Jeśli klip przesuwa postać do przodu, włącz opcję na tym klipie:
```python
shot.animation(character_fighter, FighterAnimations.GREAT_SWORD_SLASH_2,
start=57, keep_end_position=True)
shot.animation(character_fighter, FighterAnimations.GREAT_SWORD_SLASH_3, start=161)
```
`animation()` przenosi poziomy ruch kości głównej do zwykłych kluczy pozycji
aktora na ścieżce Transform. Ostatni klucz zachowuje osiągnięte przesunięcie,
więc następny atak zaczyna się w nowym miejscu. Klucze możesz edytować w Sequencerze.
Ruch pionowy i obroty kości pozostają w animacji.
### Pozostawienie postaci na ziemi po śmierci
```python
shot.animation(character_creature, CreatureAnimations.MUTANT_DYING,
start=150, keep_end_pose=True)
```
Enum bez `end` odtwarza klip raz. `keep_end_pose=True` dodaje po nim odcinek
z zamrożoną końcową pozą aż do końca sekwencji. Postać pozostaje na ziemi także
przy renderowaniu pojedynczej późniejszej klatki. Kolejna animacja tej samej
postaci kończy utrzymywanie pozy. Oryginalny klip nie jest zmieniany.
`keep_end_pose` dotyczy ułożenia kości; `keep_end_position` dotyczy przesunięcia
aktora. Można włączyć obie opcje. Jeśli jawnie wydłużysz zakres przez `end`,
klip nadal może się zapętlać w tym zakresie — dla śmierci pozostaw pojedynczy przebieg.
Aby uniknąć podwójnego przesuwania, sekcja korzysta z wygenerowanej kopii klipu
bez jego poziomego przesunięcia. Oryginalny asset animacji pozostaje bez zmian.
Opcja domyślnie jest wyłączona. Jeśli chcesz własne klucze pozycji, dodaj je po
wywołaniach `animation()` — zastąpią wygenerowane wartości na tych samych klatkach.
### Ruch względem aktualnej pozycji
Po `keep_end_position` nie musisz obliczać nowych współrzędnych ręcznie:
```python
# Po wywołaniach shot.animation(...): przesunięcie o 50 cm w osi Y.
shot.move(character_creature, start=80, end=120, offset=(0, 50, 0))
```
Helper odczyta pozycję aktora w klatce 80 z krzywych Sequencera, doda klucz
początkowy, a w klatce 120 klucz przesunięty o `offset`. To współrzędne świata
w centymetrach. Ostatnia klatka ruchu jest kluczem, więc musi być mniejsza od
`shot.frames`. Dodawaj ruch po animacjach. `move()` zastępuje klucze pozycji wewnątrz
odcinka, także wygenerowane przez `keep_end_position`. Późniejsze klucze pozycji są
przesuwane o wynikową różnicę, żeby zachować dalszy ruch. Klucze rotacji i skali zostają.
### Cofanie podczas chodzenia
`reverse=True` odtwarza klip od końca. W połączeniu z `keep_end_position=True`
odwraca także przesunięcie zapisane w klipie i zachowuje nową pozycję:
```python
shot.animation(character_creature, CreatureAnimations.MUTANT_WALKING,
start=80, end=120, reverse=True, keep_end_position=True)
```
Postać odtwarza kroki do tyłu bez zmiany kierunku, w którym patrzy. Jeśli chcesz
ustalić odległość cofnięcia samodzielnie, dopisz po animacjach:
```python
shot.move(character_creature, start=80, end=120, offset=(0, -200, 0))
```
To ustawia cofnięcie o 200 cm w osi Y; `reverse` odpowiada za kierunek odtwarzania
ruchu nóg, a `move` zastępuje trasę pozycjami wybranymi przez autora sceny.
Do własnych obliczeń służy:
```python
x, y, z = shot.position(character_creature, frame=80)
```
Odczyt uwzględnia klucze Transform, `keep_end_position` i interpolację. Nie przestawia
kursora w Sequencerze. Dotyczy pozycji aktora; ruchy samych kości wewnątrz klipu
bez `keep_end_position` nie zmieniają pozycji jego aktora. Odczyt wykonuje się w UE
podczas uruchamiania skryptu, więc VS Code nie musi znać liczbowych współrzędnych.
Listę z danymi też można odczytać bez UE:
```python
for clip in FighterAnimations:
print(clip.key, clip.seconds, clip.frames(24))
```
## Własny model studenta — generowanie automatyczne
Każde `scene.skeletal_model(...)` automatycznie zapisuje nazwy i długości jego
zaimportowanych klipów do `Content/Python/ue_workshop/animations.py`. Dotyczy to
także modeli pobranych przez studentów, FBX z animacją w środku i `.blend`.
Umieść model i jego animacje FBX w osobnym folderze, np. `source_assets/ninja`.
Przy pierwszym uruchomieniu w UE:
```python
character = scene.skeletal_model(
PROJECT / "source_assets/ninja/model.fbx",
name="Ninja",
reimport=False,
)
```
Powstanie `NinjaAnimations` — nazwa enuma wynika z `name`. VS Code zobaczy nowy
statyczny kod i będzie mógł go podpowiadać. W kolejnej edycji skryptu możesz użyć:
```python
from ue_workshop.animations import NinjaAnimations
# Jeśli w folderze był walking.fbx:
clip = NinjaAnimations.WALKING
clip.seconds
clip.frames(shot.fps)
shot.animation(character, clip, start=0)
```
Pierwszy import w UE jest potrzebny do odczytania rzeczywistych długości.
Późniejsze pisanie sceny korzysta z zapisanego katalogu i nie wymaga komend w UE.
Różnym modelom nadaj różne `name` — to również nazwa ich assetów w projekcie.
Po dodaniu FBX do folderu uruchom swój skrypt ponownie: brakujący klip zostanie
zaimportowany i dopisany do enuma. Po zmianie istniejącego klipu użyj `REIMPORT=True`;
nowa długość zapisze się automatycznie. Nie trzeba uruchamiać osobnego generatora.
`REIMPORT=False` nadal używa istniejących assetów. Nie ma sprawdzania dat źródeł.
Katalogi innych modeli pozostają w pliku. Jawny wybór `animations={...}` aktualizuje
tylko wybrane wpisy, zachowując inne znane klipy tej postaci. Automatyczny odczyt
całego folderu odświeża pełną listę. Jeśli dane się nie zmieniły, plik nie jest
zapisywany ponownie.
Opcjonalna ręczna aktualizacja dołączonego fightera i creature:
```text
python tools/run_workshop.py tools/update_animation_catalog.py
```
To narzędzie również zachowuje katalogi własnych modeli studentów.