advanced example
This commit is contained in:
1 parent
8c0a639fba
commit
6fe57915e8
99 files changed
+1329
-56
No files matched your search
@@ -0,0 +1,111 @@
|
||||
# Animacje postaci
|
||||
|
||||
`scene.skeletal_model(...)` automatycznie znajduje każdy FBX z folderu postaci
|
||||
poza plikiem samego modelu: 51 klipów fighter i 12 klipów creature.
|
||||
Wykorzystuje funkcję `_clips()` z `Content/Python/ue_workshop/characters.py`.
|
||||
Nowy FBX dodany do folderu zostanie uwzględniony przy następnym uruchomieniu skryptu.
|
||||
Trzymaj model i animacje tej samej postaci w osobnym folderze.
|
||||
|
||||
Nazwy poniżej są kluczami do `animations` i `shot.animation(...)`.
|
||||
Spacje i nawiasy z nazw plików są zamieniane na podkreślenia. Nie ma skrótów
|
||||
`idle`, `walk` i `attack`; używaj nazw takich jak `great_sword_idle` czy `mutant_swiping`.
|
||||
|
||||
Pełny przykład `examples/mixamo_characters.py` importuje wszystkie klipy.
|
||||
Plik zadania `exercises/animation_starter.py` importuje tylko dwie wybrane animacje.
|
||||
Aby udostępnić wszystkie klipy, pomiń argument `animations`:
|
||||
|
||||
```python
|
||||
character = scene.skeletal_model(CREATURE_MODEL, name="Creature", reimport=False)
|
||||
shot.animation(character, "mutant_jumping", start=240, end=360)
|
||||
```
|
||||
|
||||
Opcjonalne `animations={...}` ogranicza wybór do wskazanych plików;
|
||||
`animations={}` pozostawia tylko klipy osadzone w samym modelu.
|
||||
Krótsze klipy zapętlają się w swoim zakresie. Nakładanie zakresów automatycznie
|
||||
tworzy płynne przejście z Pythona:
|
||||
|
||||
```python
|
||||
shot.animation(character, "mutant_idle", start=0, end=60)
|
||||
shot.animation(character, "mutant_swiping", start=48, end=120)
|
||||
```
|
||||
|
||||
Wspólny zakres 48–60 miesza obie animacje przez 12 klatek (0,5 s przy 24 FPS).
|
||||
Nowy klip narasta od wagi 0 do 1, a poprzedni zanika od 1 do 0.
|
||||
Dodawaj klipy w kolejności odtwarzania. Długość blendu wynika wyłącznie z zakresów.
|
||||
Klipy stykające się końcami przechodzą bez blendu; zakresy nie mogą być identyczne
|
||||
ani całkowicie zawierać się jeden w drugim.
|
||||
Obsługiwane są przejścia między dwiema animacjami; trzy jednoczesne klipy są odrzucane.
|
||||
|
||||
|
||||
## Fighter
|
||||
|
||||
| Clip | FBX |
|
||||
|---|---|
|
||||
| `draw_a_great_sword_1` | `draw a great sword 1.fbx` |
|
||||
| `draw_a_great_sword_2` | `draw a great sword 2.fbx` |
|
||||
| `great_sword_180_turn` | `great sword 180 turn.fbx` |
|
||||
| `great_sword_180_turn_2` | `great sword 180 turn (2).fbx` |
|
||||
| `great_sword_attack` | `great sword attack.fbx` |
|
||||
| `great_sword_blocking` | `great sword blocking.fbx` |
|
||||
| `great_sword_blocking_2` | `great sword blocking (2).fbx` |
|
||||
| `great_sword_blocking_3` | `great sword blocking (3).fbx` |
|
||||
| `great_sword_casting` | `great sword casting.fbx` |
|
||||
| `great_sword_crouching` | `great sword crouching.fbx` |
|
||||
| `great_sword_crouching_2` | `great sword crouching (2).fbx` |
|
||||
| `great_sword_crouching_3` | `great sword crouching (3).fbx` |
|
||||
| `great_sword_crouching_4` | `great sword crouching (4).fbx` |
|
||||
| `great_sword_crouching_5` | `great sword crouching (5).fbx` |
|
||||
| `great_sword_crouching_6` | `great sword crouching (6).fbx` |
|
||||
| `great_sword_high_spin_attack` | `great sword high spin attack.fbx` |
|
||||
| `great_sword_idle` | `great sword idle.fbx` |
|
||||
| `great_sword_idle_2` | `great sword idle (2).fbx` |
|
||||
| `great_sword_idle_3` | `great sword idle (3).fbx` |
|
||||
| `great_sword_idle_4` | `great sword idle (4).fbx` |
|
||||
| `great_sword_idle_5` | `great sword idle (5).fbx` |
|
||||
| `great_sword_impact` | `great sword impact.fbx` |
|
||||
| `great_sword_impact_2` | `great sword impact (2).fbx` |
|
||||
| `great_sword_impact_3` | `great sword impact (3).fbx` |
|
||||
| `great_sword_impact_4` | `great sword impact (4).fbx` |
|
||||
| `great_sword_impact_5` | `great sword impact (5).fbx` |
|
||||
| `great_sword_jump` | `great sword jump.fbx` |
|
||||
| `great_sword_jump_2` | `great sword jump (2).fbx` |
|
||||
| `great_sword_jump_attack` | `great sword jump attack.fbx` |
|
||||
| `great_sword_kick` | `great sword kick.fbx` |
|
||||
| `great_sword_kick_2` | `great sword kick (2).fbx` |
|
||||
| `great_sword_power_up` | `great sword power up.fbx` |
|
||||
| `great_sword_run` | `great sword run.fbx` |
|
||||
| `great_sword_run_2` | `great sword run (2).fbx` |
|
||||
| `great_sword_slash` | `great sword slash.fbx` |
|
||||
| `great_sword_slash_2` | `great sword slash (2).fbx` |
|
||||
| `great_sword_slash_3` | `great sword slash (3).fbx` |
|
||||
| `great_sword_slash_4` | `great sword slash (4).fbx` |
|
||||
| `great_sword_slash_5` | `great sword slash (5).fbx` |
|
||||
| `great_sword_slide_attack` | `great sword slide attack.fbx` |
|
||||
| `great_sword_strafe` | `great sword strafe.fbx` |
|
||||
| `great_sword_strafe_2` | `great sword strafe (2).fbx` |
|
||||
| `great_sword_strafe_3` | `great sword strafe (3).fbx` |
|
||||
| `great_sword_strafe_4` | `great sword strafe (4).fbx` |
|
||||
| `great_sword_turn` | `great sword turn.fbx` |
|
||||
| `great_sword_turn_2` | `great sword turn (2).fbx` |
|
||||
| `great_sword_walk` | `great sword walk.fbx` |
|
||||
| `great_sword_walk_2` | `great sword walk (2).fbx` |
|
||||
| `spell_cast` | `spell cast.fbx` |
|
||||
| `two_handed_sword_death` | `two handed sword death.fbx` |
|
||||
| `two_handed_sword_death_2` | `two handed sword death (2).fbx` |
|
||||
|
||||
## Creature
|
||||
|
||||
| Clip | FBX |
|
||||
|---|---|
|
||||
| `left_turn_45` | `left turn 45.fbx` |
|
||||
| `mutant_breathing_idle` | `mutant breathing idle.fbx` |
|
||||
| `mutant_dying` | `mutant dying.fbx` |
|
||||
| `mutant_flexing_muscles` | `mutant flexing muscles.fbx` |
|
||||
| `mutant_idle` | `mutant idle.fbx` |
|
||||
| `mutant_jumping` | `mutant jumping.fbx` |
|
||||
| `mutant_left_turn_45` | `mutant left turn 45.fbx` |
|
||||
| `mutant_right_turn_45` | `mutant right turn 45.fbx` |
|
||||
| `mutant_right_turn_45_2` | `mutant right turn 45 (2).fbx` |
|
||||
| `mutant_run` | `mutant run.fbx` |
|
||||
| `mutant_swiping` | `mutant swiping.fbx` |
|
||||
| `mutant_walking` | `mutant walking.fbx` |
|
||||
+35
-4
@@ -2,6 +2,15 @@
|
||||
|
||||
Import: `from ue_workshop import Scene, Sequence, Renderer, camera, lighting, materials, assets, blender, render`
|
||||
|
||||
`REIMPORT=False` w plikach ćwiczeń używa istniejących assetów UE; brakujące są importowane.
|
||||
`REIMPORT=True` ponownie importuje modele i klipy, także po edycji `.blend`.
|
||||
Własny skrypt: `scene.skeletal_model(..., reimport=True)` lub `scene.model(..., reimport=True)`.
|
||||
Nie ma automatycznego wykrywania zmian źródeł.
|
||||
|
||||
`camera.create(..., fov=60)` ustawia poziomy kąt widzenia w stopniach: większy FOV
|
||||
daje szerszy kadr. Zakres: `0 < fov < 180`. Domyślne `43.6` odpowiada obiektywowi
|
||||
45 mm na sensorze o szerokości 36 mm.
|
||||
|
||||
| Operacja | Przykład |
|
||||
|---|---|
|
||||
| Własna mapa | `scene = Scene("MyShot")` |
|
||||
@@ -15,7 +24,7 @@ Import: `from ue_workshop import Scene, Sequence, Renderer, camera, lighting, ma
|
||||
| Korekta osi modelu przed dopasowaniem | `actor = scene.model("hero.fbx", rotation=(0, 0, 90))` |
|
||||
| Światła studyjne | `lights = lighting.studio(scene)` |
|
||||
| Pojedyncze światło | `lighting.area(scene, location=(200, -200, 350), intensity=10000, color=(1, 0.5, 0.2))` |
|
||||
| Kamera | `cam = camera.create(scene, location=(450, -550, 300), target=(0, 0, 100), focal_length=45)` |
|
||||
| Kamera | `cam = camera.create(scene, location=(450, -550, 300), target=(0, 0, 100), fov=43.6)` |
|
||||
| Zmiana kierunku | `camera.look_at(cam, (0, 0, 150))` |
|
||||
| Sekwencja | `shot = Sequence(scene, fps=24, frames=48)` |
|
||||
| Aktywna kamera | `shot.camera(cam)` |
|
||||
@@ -37,9 +46,31 @@ Cały obrót: klucze 0 i 360, nie 0 i 0. Kamera i modele to oryginalne obiekty U
|
||||
możesz wywoływać ich metody, np. `actor.set_actor_label("MyHero")`.
|
||||
`shot.asset` to oryginalny LevelSequence, `shot.bind(actor)` zwraca binding UE.
|
||||
|
||||
W `my_shot.py`: `MODEL="robot"` lub `MODEL="pilot"` wybiera dołączony model.
|
||||
`MODEL="file"` wczytuje `MODEL_FILE`. Obiekt z `scene.model()` ma pivot na podstawie
|
||||
i zachowuje materiały; animacja dotyczy całego modelu, nie jego kości.
|
||||
W `my_shot.py`: `MODEL="fighter"` lub `MODEL="creature"` wybiera postać ze szkieletem.
|
||||
Nazwy klipów pochodzą z plików, np. `great_sword_walk` i `mutant_swiping`.
|
||||
`scene.skeletal_model(...)` samo znajduje wszystkie FBX obok modelu — bez `animations`.
|
||||
Dostępne jest 51 animacji fighter i 12 animacji creature; [pełny katalog](animations.md).
|
||||
Własny FBX lub `.blend`
|
||||
z Armature: `MODEL="file"`, `SKELETAL=True`, `MODEL_FILE=...`.
|
||||
`ANIMATION_FILE=None` odtwarza animację z pliku modelu; można wskazać osobny FBX
|
||||
z animacją dla tego samego szkieletu. Dla statycznego modelu ustaw `SKELETAL=False`.
|
||||
|
||||
```python
|
||||
character = scene.skeletal_model("source_assets/character/my_character.fbx", name="Hero")
|
||||
shot.animation(character) # tylko gdy postac ma jedna dostepna animacje
|
||||
# Gdy jest ich wiecej: shot.animation(character, "nazwa_pliku_animacji")
|
||||
# Albo nazwane klipy: scene.skeletal_model(..., animations={"walk": walk_fbx, "idle": idle_fbx})
|
||||
# shot.animation(character, "walk", start=0, end=48, speed=1.0)
|
||||
# shot.animation(character, "idle", start=48, end=120)
|
||||
# Plynne przejscie: pierwszy klip 0..60, drugi 48..120:
|
||||
# shot.animation(character, "walk", start=0, end=60)
|
||||
# shot.animation(character, "idle", start=48, end=120) # automatyczny blend 12 klatek
|
||||
```
|
||||
|
||||
Krótsza animacja zapętla się w swojej sekcji. `transform_key` porusza całym aktorem
|
||||
równolegle z animacją kości. Do własnych tras wybieraj klipy In Place.
|
||||
Blender: kolekcja `Character`, siatki przypisane do jednego Armature, aktywna akcja
|
||||
i zakres klatek sceny. Zapisz plik przed ponownym uruchomieniem skryptu w UE.
|
||||
|
||||
Przy pojedynczym podglądzie nie uruchamiaj dodatkowo pełnego renderu:
|
||||
jednocześnie może pracować tylko jeden renderer warsztatowy.
|
||||
@@ -38,3 +38,65 @@ Nie uruchamiano testów na Linuksie ani na Blenderze 4.x.
|
||||
Uruchamianie sprawdzeń jest opisane w README. Wyniki każdego renderu są zapisane
|
||||
w jego `result.json`; logi UE znajdują się w `Saved/Logs`.
|
||||
Skrypty integracyjne generują własne mapy i assety w `Workshop/Generated`.
|
||||
|
||||
## Postacie szkieletowe — 31 października 2026
|
||||
|
||||
- 13 testów poza UE: w tym zakresy klipów, wykrywanie nakładania, prędkość,
|
||||
wybór klipu i odrzucanie animacji z innym szkieletem.
|
||||
- UE 5.7: import fighter i creature jako SkeletalMesh z materiałami i teksturami,
|
||||
własny szkielet każdej postaci oraz klipy idle, walk i attack z osobnych FBX.
|
||||
- W klipach walk sprawdzone rzeczywiste zmiany rotacji kości między klatkami.
|
||||
- Ponowny import tych samych assetów po restarcie UE oraz zapis zależności
|
||||
(szkielet, materiały, tekstury). FBX używa importera zgodnego z FbxImportUI;
|
||||
poprzednia wartość flagi Interchange jest przywracana po imporcie.
|
||||
- Sequencer: klipy w kolejnych zakresach, prędkość 0.75 i jednoczesne klucze
|
||||
transformacji rodzica. Render 48 klatek, 640×360, dla obu postaci.
|
||||
- Blender 5.1.2: wczytanie fighter i chodzenia z nowych FBX wyeksportowanych
|
||||
przez UE, zmiana geometrii z zachowaniem wag, zapis `.blend`, eksport Armature
|
||||
i aktywnej akcji, import do UE i render 24 klatek, 640×360.
|
||||
- Dołączone źródła są w FBX 6.1, nieobsługiwanym przez importer Blendera 5.1;
|
||||
bezpośredni import w UE działa. Test Blendera korzysta z eksportu UE do FBX 7.3.
|
||||
|
||||
Odtworzenie testu Blendera (po teście `smoke_skeletal.py`):
|
||||
|
||||
```text
|
||||
blender --background --python-exit-code 1 --python tools/create_skeletal_fixture.py
|
||||
python tools/run_workshop.py tools/smoke_skeletal_blender.py --render
|
||||
```
|
||||
|
||||
Eksport szkieletowy obejmuje jedną postać i aktywną akcję w zakresie sceny.
|
||||
Nie sprawdzano retargetingu, Animation Blueprintów ani eksportu wielu akcji/NLA.
|
||||
|
||||
## Pliki na zajęcia i pełne katalogi
|
||||
|
||||
- `tools/smoke_workshop_files.py`: w UE zaimportowano wszystkie 51 klipów fighter
|
||||
i 12 klipów creature; sprawdzono kompletność słowników i dodatnią długość klipów.
|
||||
- `exercises/basics.py`: eksport własnego `.blend`, 192 klatki kamery na okręgu,
|
||||
stały promień, zgodne końce trasy i ciągły yaw obejmujący pełne 360°.
|
||||
- `exercises/animation_starter.py`: jedna postać, dokładnie dwa klipy, 360 klatek.
|
||||
- Wszystkie trzy sceny zostały zbudowane i zapisane w oddzielnych mapach.
|
||||
|
||||
## Blendowanie z Pythona
|
||||
|
||||
- 17 testów poza UE: dodatkowo poprawne nakładanie, wagi obu klipów, zachowanie
|
||||
wejścia i wyjścia środkowego klipu oraz odrzucanie trzech równoczesnych klipów.
|
||||
- `tools/smoke_blending.py`: w UE 5.7 utworzono przejścia idle → attack → walk,
|
||||
po 12 klatek każde. Sprawdzone zapisane klucze Weight i wyrenderowana klatka 54,
|
||||
w środku pierwszego przejścia, równolegle z kluczami pozycji rodzica.
|
||||
- Przejście korzysta z kanałów wag; chronione pola MovieSceneEasingSettings
|
||||
nie są modyfikowane. Modele i klipy są ponownie używane z `reimport=False`.
|
||||
|
||||
## Automatyczne wykrywanie bez aliasów
|
||||
|
||||
- 23 testy poza UE: dodatkowo pomijanie pliku modelu, nazwy z plików, wykrywanie
|
||||
kolizji nazw, automatyczny wybór wszystkich klipów, jawny wybór i puste `animations={}`.
|
||||
- Sprawdzone przekazywanie `reimport=False`/`True` oraz użycie istniejącego modelu.
|
||||
- `tools/smoke_workshop_files.py` zaliczony w UE: obie postacie wczytane bez
|
||||
argumentu `animations`, pełne 51 + 12 klipów i plik zadania z dwoma pełnymi nazwami.
|
||||
|
||||
## Automatyczny blend
|
||||
|
||||
- 26 testów poza UE: blend wynika ze wspólnego zakresu, także przy jednej klatce
|
||||
nakładania; stykające się klipy nie dostają fade. Sprawdzone łańcuchy trzech
|
||||
klipów oraz odrzucanie niejednoznacznych zakresów i dodawania w odwrotnej kolejności.
|
||||
- Parametr `blend_in` usunięty z API i przykładów. Zakresy scen pozostają takie same.
|
||||
Reference in new issue
Block a user