Работа в Unreal Engine 5 с помощью GPT

—

от автора

Автор статьи: Ростислав Мусиенко

Senior Unreal Engine Developer в District Zero

Все уже знакомы с игровым движком Unreal Engine 5. И экспериментировали или слышали о GPT chat. Я решил провести эксперимент и проверить насколько чат способен генерировать нестандартный код C++ для объектов в Unreal Engine

Решил начать с простого, сделать дверь которая будет открываться когда подходит персонаж, сделал небольшой запрос

В ответ мне было предложено следующее.

Откройте файл MyActorDoor.cpp и добавьте следующий код:

#include "MyActorDoor.h" #include "Components/StaticMeshComponent.h" #include "GameFramework/Actor.h"  AMyActorDoor::AMyActorDoor() {     // Set this actor to call Tick() every frame.     PrimaryActorTick.bCanEverTick = true;      // Create the static mesh component for the door     DoorMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("DoorMesh"));     RootComponent = DoorMesh;      // Set the default door rotation     TargetRotation = FRotator(0.f, 90.f, 0.f); }  void AMyActorDoor::BeginPlay() {     Super::BeginPlay(); }  void AMyActorDoor::Tick(float DeltaTime) {     Super::Tick(DeltaTime);      // If the door should be opened, interpolate the rotation     if (bShouldOpen)     {         FRotator CurrentRotation = DoorMesh->GetComponentRotation();         FRotator NewRotation = FMath::RInterpTo(CurrentRotation, TargetRotation, DeltaTime, 2.f);         DoorMesh->SetWorldRotation(NewRotation);          // Check if the door is fully opened         if (CurrentRotation.Equals(TargetRotation, 1.f))         {             bShouldOpen = false;         }     } }  void AMyActorDoor::OpenDoor() {     bShouldOpen = true; } 

Откройте файл MyActorDoor.h и добавьте следующий код:

#pragma once  #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MyActorDoor.generated.h"  UCLASS() class GPT_TEST_API AMyActorDoor : public AActor {     GENERATED_BODY()  public:     // Sets default values for this actor's properties     AMyActorDoor();      // Called every frame     virtual void Tick(float DeltaTime) override;      // Function to open the door     UFUNCTION(BlueprintCallable, Category = "Door")     void OpenDoor();  protected:     // Called when the game starts or when spawned     virtual void BeginPlay() override;  private:     // Static mesh component for the door     UPROPERTY(VisibleAnywhere)     UStaticMeshComponent* DoorMesh;      // The target rotation for the door when it's fully opened     FRotator TargetRotation;      // Flag to determine if the door should be opened     bool bShouldOpen; }; 

Увидев код, который мне проложил чат, я был воодушевлен. Он понимал конструкции и связи в движке а так же был знаком с синтаксисом.
Далее, переведя класс в блупринт и добавив меш двери я пошел проверять.
Очевидно он не работал потому, что нигде не применялось само событие для открытия двери.

Я понял что на этом вся простота и удобство закончились, и далее пытаясь починить код точечно это уже не давалось так легко.

Добавив измененный код после этого запроса все сломалось, и следующей целью было с помощью чата постараться починить код.

Он предлагал обрывочные решения, после которых появлялись новые ошибки.

После череды попыток код снова компилировался и пришло время его проверять.
Теперь он работал как требовалось. Открывал дверь после того как персонаж к ней подходил.

Далее задача была усложнена, сделать класс турели которая будет следить за игроком.

Первоначально был выслан только .cpp код и даже в нем не хватало логики для итоговой реализации как логики стрельбы например (возможно потому что ранее небыло предусмотрено снарядов или способов того как будет производится стрельба)

#include "TurretActor.h" #include "GameFramework/SpringArmComponent.h" #include "Camera/CameraComponent.h" #include "Kismet/GameplayStatics.h" #include "Components/BoxComponent.h" #include "Components/StaticMeshComponent.h" #include "TimerManager.h"  // Sets default values ATurretActor::ATurretActor() {     // Set this actor to call Tick() every frame.     PrimaryActorTick.bCanEverTick = true;      // Create the base mesh component     BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BaseMesh"));     RootComponent = BaseMesh;      // Create the turret mesh component     TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("TurretMesh"));     TurretMesh->SetupAttachment(BaseMesh);      // Create the gun mesh component     GunMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("GunMesh"));     GunMesh->SetupAttachment(TurretMesh);      // Create the collision box for player detection     PlayerDetectionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("PlayerDetectionBox"));     PlayerDetectionBox->SetupAttachment(GunMesh);      // Set up initial rotation values     BaseRotationSpeed = 20.0f;     TurretRotationSpeed = 10.0f;     GunRotationSpeed = 5.0f;      // Set up the delay between shots and shooting range     ShootDelay = 2.0f;     ShootingRange = 1000.0f; }  // Called when the game starts or when spawned void ATurretActor::BeginPlay() {     Super::BeginPlay();      // Set up the player character reference     ACharacter* PlayerCharacter = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);     if (PlayerCharacter)     {         PlayerCharacterRef = PlayerCharacter;     }      // Start the shooting timer     GetWorldTimerManager().SetTimer(ShootTimerHandle, this, &ATurretActor::Shoot, ShootDelay, true); }  // Called every frame void ATurretActor::Tick(float DeltaTime) {     Super::Tick(DeltaTime);      // Rotate the turret base towards the player     if (PlayerCharacterRef)     {         FVector PlayerLocation = PlayerCharacterRef->GetActorLocation();         FVector TurretLocation = TurretMesh->GetComponentLocation();         FRotator LookAtRotation = (PlayerLocation - TurretLocation).Rotation();         FRotator BaseRotation = FRotator(0.f, LookAtRotation.Yaw, 0.f); // Only yaw rotation          FRotator NewBaseRotation = FMath::RInterpTo(BaseMesh->GetComponentRotation(), BaseRotation, DeltaTime, BaseRotationSpeed);         BaseMesh->SetWorldRotation(NewBaseRotation);          // Rotate the turret towards the player         FRotator NewTurretRotation = FMath::RInterpTo(TurretMesh->GetComponentRotation(), LookAtRotation, DeltaTime, TurretRotationSpeed);         TurretMesh->SetWorldRotation(NewTurretRotation);          // Rotate the gun towards the player         FRotator GunLookAtRotation = (PlayerLocation - GunMesh->GetComponentLocation()).Rotation();         FRotator NewGunRotation = FMath::RInterpTo(GunMesh->GetComponentRotation(), GunLookAtRotation, DeltaTime, GunRotationSpeed);         GunMesh->SetWorldRotation(NewGunRotation);          // Check if the turret is facing the player and within shooting range         FVector ToPlayer = PlayerLocation - GunMesh->GetComponentLocation();         float DotProduct = FVector::DotProduct(ToPlayer.GetSafeNormal(), GunMesh->GetForwardVector());         if (DotProduct > 0.99f && ToPlayer.Size() <= ShootingRange)         {             // Fire when facing the player             Shoot();         }     } }  void ATurretActor::Shoot() {     // Implement your shooting logic here     // You can spawn projectiles or apply damage to the player, for example }  // Other functions and logic can be added as needed 

Для того чтобы проверить работу хотя бы того когда, требовались файлы заголовков, и я достаточно просто их получил

#pragma once  #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "TurretActor.generated.h"  UCLASS() class GPT_TEST_API ATurretActor : public AActor {     GENERATED_BODY()  public:     // Sets default values for this actor's properties     ATurretActor();  protected:     // Called when the game starts or when spawned     virtual void BeginPlay() override;  public:     // Called every frame     virtual void Tick(float DeltaTime) override;  private:     // Base mesh component     UPROPERTY(VisibleAnywhere)     UStaticMeshComponent* BaseMesh;      // Turret mesh component     UPROPERTY(VisibleAnywhere)     UStaticMeshComponent* TurretMesh;      // Gun mesh component     UPROPERTY(VisibleAnywhere)     UStaticMeshComponent* GunMesh;      // Collision box for player detection     UPROPERTY(VisibleAnywhere)     UBoxComponent* PlayerDetectionBox;      // Player character reference     ACharacter* PlayerCharacterRef;      // Rotation speeds     UPROPERTY(EditAnywhere)     float BaseRotationSpeed;      UPROPERTY(EditAnywhere)     float TurretRotationSpeed;      UPROPERTY(EditAnywhere)     float GunRotationSpeed;      // Shooting parameters     UPROPERTY(EditAnywhere)     float ShootDelay;      UPROPERTY(EditAnywhere)     float ShootingRange;      FTimerHandle ShootTimerHandle;      // Function to handle shooting     void Shoot(); }; 

Однако, в итоге, стоит отметить, что попытки решения проблемы с помощью чат-бота оказались неэффективными. Главной причиной этого оказалось ограничение по объему текста, так как целиком код .cpp и .h файлов не уместился в одном ответе. Это означает, что некоторые важные части кода и объявления в заголовочных файлах не были видны чат-боту, что делало невозможным диагностику и решение проблемы.

Чат-бот GPT имеет свои ограничения и он не способен самостоятельно создавать полностью работоспособный код даже для легких объектов. Разработка программного обеспечения требует глубокого технического понимания, архитектурного проектирования и знания специфических инструментов и библиотек.

Они не способны:

  1. Создавать проекты с нуля;

  2. Генерировать сложный и эффективный код;

  3. Понимать специфические требования проекта;

  4. Решать проблемы без контекста.

Несмотря на это есть и плюсы можно сделать вывод о полезности использования GPT в разработке, а именно:

  1. Поиск документации и решений;

  2. Исправление ошибок в коде;

  3. Подсказки по оптимизации.

Следует помнить об ограничениях GPT и его текущих возможностях создания кода для  Unreal Engine. Важно понимать, что GPT не является заменой опыта и компетенции разработчика. Он может быть полезным инструментом, но не всегда предоставляет исчерпывающие и точные ответы, особенно при сложных проблемах.

В будущем, с развитием искусственного интеллекта, возможно, GPT станет более мощным инструментом для разработчиков. Он сможет предоставлять более точные рекомендации и, возможно, даже генерировать части кода или ассеты для игр. Однако на данный момент основной путь к успешной разработке остается в обучении и практике.

Таким образом важно постоянно совершенствовать свои навыки и обучаться программированию, а также изучать работу движка Unreal Engine для достижения успешных результатов в разработке игр и приложений.

Для этого хотим предложить вам уникальную возможность углубить свои знания и навыки в разработке игр и виртуальных миров. OTUS предлагает вам посетить бесплатный вебинар, где погрузимся в мир Unreal Engine и научимся создавать эффект взрыва с использованием Niagara System. Разберем основы работы в Niagara и пройдем через процесс создания собственного эффекта взрыва, включая добавление собственных эмиттеров.


ссылка на оригинал статьи https://habr.com/ru/articles/761288/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *