UE4 Einsteigerhilfe mit Schwerpunkt C++ (dynamisches Erzeugen PAWN dynamisch mit Code erstellen/spawnen, Zugriff auf Mesh/Skelett, Skelett bewegen ohne reine Animation) gesucht (für private Freizeitprogrammierung)

  • UE4 Einsteigerhilfe mit Schwerpunkt C++ (dynamisches Erzeugen PAWN dynamisch mit Code erstellen/spawnen, Zugriff auf Mesh/Skelett, Skelett bewegen ohne reine Animation) gesucht (für private Freizeitprogrammierung)

    Hallo zusammen,

    ein Kumpel und ich wollen die Bewegnung von verschiedenen simplen "Kreaturen" mit x-Beinen aus Spaß an der Freude in unserer Freizeit simulieren und würden dies gerne mit der UE4 und Schwerpunkt auf C++ und Machine Learning angehen. Leider haben wir keine Erfahrung in Spieleengine, sind aber versierte C++-Programmierer (C++11) mit Physikstudium.

    Aktuell scheitern wir daran einen guten Einstieg zu finden, teils, da es hart ist von der reinen API-Klassen-Übersicht aus zu starten und die Tutorial bisher nicht so hilfreich waren und aufgrund älterer UE4 Version (vs 4.15) of nicht kompatibel waren. Auch sind wir beide beruflich in der Woche immer eng eingefercht und uns fehlt die Zeit die richtigen Tutoriale zu finden oder die Essenz auch etlichen herauszuziehen, gute Bücher habe ich bisher nicht im Netz gefunden.
    Wir würden uns über eine Einführung (gerne mal eine Art Seminar für einen Tag, falls jemand von Euch uns hier eine gute Einführung für einen vertrebaren Preis geben könnte) oder nützliche Links freuen:

    Soweit ich es verstanden habe, benötige ich Verständnis (möglichst auf C++-Basis und weniger auf Blueprints)
    - der einzelnen Klassen und API von UE4 um das größere Konzept und die Wechselwirkungen zu verstehen, sowie was für was am besten genutzt wird und was Performance technisch zielführend ist
    - über PAWN und ACTOR-Klassen (dynamische Erzeugung/Spawnen)
    - wie Meshes/SkeletalMesh und Skelet mit einem PAWN verknüpft werden können
    - wie ich die Knochen/Gelenke nutzen und per C++ ansteuern und auslenken kann
    - asynchrone Einbindung von Berechnungen für neuronale Netzwerke, die von der Frame-Rate entkoppelt werden und dann ab und an ein Update der AI liefern

    Aktuell haben wir vorgesehen per Blender einfache "tischartige" Wesen mit 4 Beinen und Skelett als fbx zu exportieren und zu verwenden.

    Freue mich über Rückmeldungen, Lins etc.
  • Hallo,
    einen Einstieg in die verfügbaren Klassen gibt es hier. docs.unrealengine.com/latest/INT/API/QuickStart/index.html

    Wichtig ist, dass die jeweiligen Module im Build Target angegeben werden.

    C-Quellcode: MyGame.Build.cs

    1. public class MyGame : ModuleRules
    2. {
    3. public MyGame(TargetInfo Target)
    4. {
    5. PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AIModule", "RHI" });
    6. // Uncomment if you are using online features
    7. // PrivateDependencyModuleNames.Add("OnlineSubsystem");
    8. }
    9. }
    Alles anzeigen


    Das Spiel wird über den GameMode her aufgebaut. Darin werden die zu verwendenden Klassen für Controller, Pawn und soweiter festgelegt und die Bedingungen für Sieg und Niederlage bzw. Spielregeln definiert.

    Alles, was in der Welt gespawnt werden kann erbt von AActor bzw. Kindern von AActor.

    Quellcode

    1. GetWorld()->SpawnActor<AItem>(AItem::StaticClass(), Transform, Params);
    docs.unrealengine.com/latest/I…d/SpawnActor/4/index.html

    Ihr könnt in der Dokumentation alle Funktionsnamen eingeben und erhaltet zu den meisten davon einen aussagekräftigen Beispielcode.


    Über Pawn und Actor Klassen:
    Wie oben bereits erwähnt sind alle spawnfähigen Klassen Kinder von AActor. Pawn erbt direkt von AActor und erweitert die Funktionalität um die Möglichkeit, den Actor durch einen Controller steuern zu können.

    docs.unrealengine.com/latest/I…ramework/APawn/index.html

    Es gibt 3 Kinder von APawn, die in Frage kommen: (1) ACharacter, (2) ADefaultPawn und (3)AWheeledVehicle.
    1: Mesh, Collision und eingebaute Bewegungslogik sind hier bereits Implementiert. Die sind dazu gedacht, dass man sich damit am Boden fortbewegen kann.
    2: Mesh, einfache Collision und andere Movement Logik für fliegende Pawns.
    3: Mesh, Collision, Bewegung eines Fahrzeugs.

    In der Dokumentation steht eigentlich alles was ihr dazu wissen müsst.


    -wie Meshes/SkeletalMesh und Skelet mit einem PAWN verknüpft werden können
    - wie ich die Knochen/Gelenke nutzen und per C++ ansteuern und auslenken kann

    docs.unrealengine.com/latest/I…/USkeletalMesh/index.html

    Ob ihr da komplett ohne Blueprints auskommen könnt, weiß ich nicht genau. Die Klasse hält jedenfalls die Schnittstelle zu SkeletalMeshes bereit. Da würde ich aber noch mal in den Editor gucken, da eröffnen sich mehr Möglichkeiten.


    Von Neuronalen Netzen verstehe ich nicht viel. Die Asynchronität sollte mit WorkerThreads machbar sein und nach jedem Durchlauf irgend eine Variable setzen, die von der AI jeden Tick gelesen und verwendet wird.
    wiki.unrealengine.com/Multi-Th…_to_Create_Threads_in_UE4

    Ich hoffe das gibt euch genügend Anhaltspunkte, um starten zu können.

    Viele Grüße.
    MAXX
  • Hallo MAXX,

    vielen Dank erst mal für den ausführlichen Überblick, werde mich am WE mal gleich versuchen drauf zu stürzen :)

    Wie sind eigentlcih die Performance (CPU/RAM/VRAM/GPU) Restrikionen, wieviele PAWN sollte man maximal haben, wie groß (kB /MB) sollte eine Kreatur/ ein Objekt als fbx maximal sein? ICh habe mal gelesen, dass man ca. 30 FPS anstreben sollte und damit dynamisch die Performance prüft?

    Beste Grüße
    Gerald
  • Pydraktor schrieb:

    Wie sind eigentlcih die Performance (CPU/RAM/VRAM/GPU) Restrikionen, wieviele PAWN sollte man maximal haben, wie groß (kB /MB) sollte eine Kreatur/ ein Objekt als fbx maximal sein? ICh habe mal gelesen, dass man ca. 30 FPS anstreben sollte und damit dynamisch die Performance prüft?

    Das lässt sich pauschal nicht sagen. Die Hardware ist ausschlaggebend. Es kommt also ganz auf die Zielgruppe und deren Rechner an. Da ich eher wenig Erfahrungswerte diesbezüglich habe, hab ich da keine genauen Werte im Kopf.

    Wieviele Pawns? So viele du willst. Aber es kommt eben drauf an. Wenn jeder Pawn in jedem Tick sehr viele Operationen durchführen soll, kannst du eben nicht 10 000 davon haben.

    Ebenso verhält es sich mit den Polys und Texturen von Skeletal Meshes. Wenn du nur einen großen Tentakeldrachen mit (bauchgefühl, keine Ahnung) 100 000 Tris darstellen willst, sollte das gehen, wird aber vielleicht nicht so gut auf dem Handy laufen.

    Die dargestellten Objekte und Texturen sollten allesamt bequem in den Grafikspeicher passen, dann sollte alles flüssig laufen. Je nachdem, was ihr anstrebt, sind das heutzutage 2 bis 8 GB.


    30 fps sind das absolute Minimum für "normale" Spiele. Wenn du einen modernen, guten Rechner hast, dann peile lieber 90 fps an. Bei VR sollten es gegen 90 fps sein, um movement distortion und motion sickness zu verhindern. Es kommt also immer ganz drauf an, was man machen will. In shootern sind 30fps auch eher schlecht.

    Im Level Preview oben links der kleine Pfeil neben der Perspektive-> Stat -> Engine -> Detailed. Dort kannst du ausgeben lassen, wieviele Millisekunden für den Frame gebraucht werden und welcher Bereich am langsamsten ist.
    Außerdem sind Stat -> Advanced -> GPU / Memory interessant. Einfach anhaken, schauen worauf sich der Wert einpendelt und den Pawn mal in die Welt ziehen und wieder schauen, wie der Wert ist.

    Ich hoffe ich konnte helfen, auch wenn es dazu keine Lehrbuchzahlen gibt.
    Viele Grüße,
    Mario
  • Die Stats sind nützlich, danke für den Tipp.

    Ich habe es geschafft mein Blender Mesh zuspawnen. Jetzt hatte ich gedacht, ich könnte die Knochen ansteuern und z. B. einfach mal zum Test einen rotieren. Hierzu wollte ich eine UPoseableMeshComponent und die Funktion GetBoneRotationByName sowie SetBoneRotationByName mittels eines FRotator-Objektes nutzen. Angeblich routiert auch die Knochen, allerdings sehe ich davon in der Anwendung nichts. Was mache falsch? Code siehe unten.


    Mir ist leider auch noch nicht ganz die Verkettung der ganzen Klassen klar.


    Ich habe einen Pawn, dieser besitzt ein Mesh, z. B. ein USkeletalMesh oder ein UPoseableMesh? Letzteres hat Knochen, hinzu kommt noch eine USceneComponent, die ich als RootComponent nutze. Was steuert denn nun eigentlich was, wie bekomme ich die PhysikEngine hinzu, was wird wann wie angezeigt und verändert, wie verkette ich alles?


    Schon mal vielen Dank für die Hilfe :)

    Quellcode

    1. UCLASS()
    2. class SPAWNPAWN_API APawnToSpawn : public APawn
    3. {
    4. GENERATED_BODY()
    5. public:
    6. // Sets default values for this pawn's properties
    7. APawnToSpawn();
    8. protected:
    9. // Called when the game starts or when spawned
    10. virtual void BeginPlay() override;
    11. public:
    12. // Called every frame
    13. virtual void Tick(float DeltaTime) override;
    14. // Called to bind functionality to input
    15. virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    16. USkeletalMeshComponent* m_mesh;
    17. UPoseableMeshComponent* m_mesh_posable;
    18. USceneComponent* m_scene; //als Rootobject
    19. };
    20. APawnToSpawn::APawnToSpawn()
    21. {
    22. // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
    23. PrimaryActorTick.bCanEverTick = true;
    24. m_mesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("Mesh_PawnToSpawn"));
    25. //m_mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh_PawnToSpawn"));
    26. m_mesh_posable = CreateDefaultSubobject<UPoseableMeshComponent>(TEXT("Posable_Mesh_PawnToSpawn"));
    27. m_scene = CreateDefaultSubobject<USceneComponent>(TEXT("Scene_Object"));
    28. RootComponent = m_scene;
    29. ConstructorHelpers::FObjectFinder<USkeletalMesh> meshFinder(ANSI_TO_TCHAR("/Game/Assets/TableTEst3"));
    30. //ConstructorHelpers::FObjectFinder<UStaticMesh> meshFinder(ANSI_TO_TCHAR("/Game/StarterContent/Props/SM_Chair"));
    31. //SkeletalMesh'/Game/TableTEst3.TableTEst3'
    32. UE_LOG(LogTemp, Log, TEXT("meshFinder.Succeeded() = %i"), meshFinder.Succeeded());
    33. if (meshFinder.Succeeded())
    34. {
    35. m_mesh->SetSkeletalMesh(meshFinder.Object);// SetStaticMesh, Skeletal mesh
    36. m_mesh_posable->SetSkeletalMesh(meshFinder.Object);
    37. m_mesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform, TEXT("Socket1"));
    38. m_mesh_posable->AttachToComponent(RootComponent,FAttachmentTransformRules::KeepRelativeTransform , TEXT("Socket1"));
    39. }
    40. }
    41. // Called when the game starts or when spawned
    42. void APawnToSpawn::BeginPlay()
    43. {
    44. Super::BeginPlay();
    45. //m_mesh->AddForce(FVector(10.f, 0.f, 0.f));
    46. FRotator rotator = m_mesh_posable->GetBoneRotationByName("bonedown4_end", EBoneSpaces::ComponentSpace);
    47. UE_LOG(LogTemp, Log, TEXT("rotator bonedown4_end = %d %d %d"), rotator.Pitch, rotator.Yaw, rotator.Roll);
    48. rotator.Pitch = rotator.Pitch + 2;
    49. rotator.Yaw = rotator.Yaw + 1;
    50. rotator.Roll = rotator.Roll + 2;
    51. m_mesh_posable->SetBoneRotationByName("bonedown4_end", rotator, EBoneSpaces::ComponentSpace);
    52. rotator = m_mesh_posable->GetBoneRotationByName("bonedown4_end", EBoneSpaces::ComponentSpace);
    53. UE_LOG(LogTemp, Log, TEXT("rotator bonedown4_end = %d %d %d"), rotator.Pitch, rotator.Yaw, rotator.Roll);
    54. //m_mesh_posable->GetBoneMatrix(1);
    55. }
    Alles anzeigen
  • Update:

    Mit UPoseableMeshComponent kann ich nun eine Knochen bewegen, hatte leider den untersten Knochen verwendet, der keine Auswirkung hatte ^^. Leider bekomme ich aber keine physikalischen Effekte in UPoseableMeshComponent rein. Mit USkeletalMeshComponent funktioniert die Physik allerdings generell, hier ist mir allerdings wieder unklar, wie ich:


    1. die Knochen einzeln bewegen kann. Ziel ist es wie im Bild unten zu sehen einen Tisch, der aus einzelnen Knochen (3 je Tischbein) besteht zu bewegen, jedoch ohne vorgespeicherte Animationen, sondern mit Auslenkenunge der Gelenke der Knochen und unter Berücksichtigung der Physik.
    2. der vordere Tisch ist ein UPoseableMeshComponent und die Physik wirkt gar nicht, kann keine Masse zu weisen
    3. der hintere Tisch (ja er sieht nicht so aus!) ist identisch mit dem vorderen, aber die Physik dreht ab, hierbei handelt es sich um USkeletalMeshComponent. K. A. warum der hintere wie wild springt und sich verdreht ohne zu stoppen - ist absolut unphysikalisch, Physik ist an.
    4. Hab schon versucht UPoseableMeshComponent und USkeletalMeshComponent gleichzeitig zu verwenden und die UPoseableMeshComponent an USkeletalMeshComponent zu attachen und USkeletalMeshComponent auf unsichtbar zu stellen. Ist ggf. UPoseableMeshComponent gar nicht für mich relevant?
    5. Bilder 2 und 3 zeigen den Aufbau des Tisches aus Knochen, verstehe bereits nicht, warum der 2. unterste und der unterste Knochen verschiedene Eigenschaftsoptionen in der rechten Leiste haben. U. A. hat der unterste keine Masse? Muss ich ggf. hier noch Boundaries einbauen oder Meshes um diese eingentartigen Verformungen zu verhindern, ggf. Steifheit?
    Bin für jede Hilfe dankbar. Aktuell brauche ich immer ca. einen Tag mit 8h, nur um einen winzigen Schritt vorwärts zu kommen :( - die Dokumentation ist für jemanden ihne Engine-Kenntnisse noch sehr lückenhaft - k. A. für was man nun wirklich welche Klasse verwendet, trotz massiver Suchen in der API und im I-Net.
    Bilder
    • 1.jpg

      346,49 kB, 1.920×1.200, 9 mal angesehen
    • 2.jpg

      295,75 kB, 1.920×1.200, 4 mal angesehen
    • 3.jpg

      286,4 kB, 1.920×1.200, 3 mal angesehen
Unreal®, Unreal Engine, the circle-U logo and the Powered by Unreal Engine logo are trademarks or registered trademarks of Epic Games, Inc. in the United States and elsewhere.