Skip to content

Instantly share code, notes, and snippets.

@derofim
Last active May 2, 2017 08:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save derofim/9a307a6c138b0726b4b1f5ad979554fd to your computer and use it in GitHub Desktop.
Save derofim/9a307a6c138b0726b4b1f5ad979554fd to your computer and use it in GitHub Desktop.
Шутер от первого лица

По материалам https://docs.unrealengine.com/latest/INT/Programming/Tutorials/FirstPersonShooter/index.html
Дополнительно:

  • Уничтожаемые объекты, удаление объектов
  • Цвет папки
  • Collections
  • Бег (Sprint)

Editor Startup Map

Создаем C++ -> Basic Code Project -> With Starter Content называем его "MyTestProject".

Для урока понадобятся 3д модели с формой столкновений, мы будем использовать стандартные (если проект With Starter Content).
Включите в настройках View Options внутри Content Browser галочки Show Engine Content для просмотра скрытого стандартного контента.

content

В Content Browser создаем папку "ProjectContent", а в ней подпапки Blueprints, Maps, Models, Textures.

При желании вы можете изменить цвет папки кликнув на ней Правой Кнопкой Мыши (ПКМ) и выбрав пункт "set colour":

  • Анимации зеленые
  • Скелетные меши розовые
  • Карты оранжевые

Сохраняем карту через File -> Save as в папку ProjectContent->Maps под названием FPSMap.

В Edit->Project Settings во вкладке Maps & Modes устанавливаем FPSMap как Editor Startup Map

Сохраняем все через File -> Save All (Ctrl+Shift+S)

Collections

Для более удобного поиска вы можете добавить часто используемые внутри Content Browser файлы в коллекции.
Collections - персонализированные группы ссылок на файлы.
Для этого в View Options включите Show Collections.
ViewCollections
Раскройте в Content Browser боковую панель нажав на иконку "Show or hide sources panel", находящуюся рядом с Filters и полем поиска.
Создайте коллекцию нажав на иконку "+":
AddNewCollections
Для добавления в коллекцию достаточно перетащить в нее asset:
AddNewCollections

см. подробнее на https://docs.unrealengine.com/latest/INT/Engine/Content/Browser/UserGuide/Collections/

GameMode

Открываем редактор кода File -> Open Visual Studio
Добавляем в MyTestProjectGameModeBase.h:

virtual void StartPlay() override;

Добавляем в MyTestProjectGameModeBase.cpp:

void AMyTestProjectGameModeBase::StartPlay()
{
	Super::StartPlay();

	if (GEngine)
	{
		// Display a debug message for five seconds. 
		// The -1 "Key" value (first argument) indicates that we will never need to update or refresh this message.
		GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Yellow, TEXT("Hello World, this is FPSGameMode!"));
	}
}

Сохраняем все, Компилируем код.
Создадим внутри папки Blueprints подпапки Characters, Controllers, GameMode, HUD, Projectile.
Создадим Blueprint class на основе MyTestProjectGameModeBase (/Script/MyTestProject.MyTestProjectGameModeBase).
Для этого в Content Browser выбираем ПКМ MyTestProjectGameModeBase и выбираем пункт Create Blueprint class based on MyTestProjectGameModeBase.
Сохраняем под именем BP_MyTestProjectGameModeBase в папку ProjectContent/Blueprints/GameMode.
В Edit->Project Settings во вкладке Maps & Modes устанавливаем BP_MyTestProjectGameModeBase как Default GameMode

Character

Добавляем в Unreal Editor новый C++ класс через File -> New C++ Class, выбираем родительский класс (Choose Parent Class) равным Character и называем как FPSCharacter.
Заменяем функцию BeginPlay в FPSCharacter.cpp на:

// Called when the game starts or when spawned
void AFPSCharacter::BeginPlay()
{
	Super::BeginPlay();
	if (GEngine)
	{
		// Put up a debug message for five seconds. The -1 "Key" value (first argument) indicates that we will never need to update or refresh this message.
		GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, TEXT("We are using FPSCharacter."));
	}
}

Сохраняем все, Компилируем код.
Создадим Blueprint class на основе FPSCharacter.
Для этого в Content Browser выбираем ПКМ MyTestProjectGameModeBase и выбираем пункт Create Blueprint class based on FPSCharacter.
Сохраняем под именем BP_FPSCharacter в папку ProjectContent/Blueprints/Characters.
В Edit->Project Settings во вкладке Maps & Modes (Selected GameMode) устанавливаем BP_FPSCharacter как Default Pawn

Сохраняем все, Компилируем код, Компилируем Blueprints.
При запуске игры игрок должен перестать двигаться.

Axis Mapping

Axis Mappings позволяют управлять клавиатурой

В Edit->Project Settings во вкладке Input

Добавляем в Bindings следующие Axis Mappings:
MoveForward

  • W : Scale 1.0
  • S : Scale -1.0 MoveRight
  • D : Scale 1.0
  • A : Scale -1.0 Turn
  • Mouse X : Scale 1.0 LookUp
  • Mouse Н : Scale -1.0

Axis Mappings
Axis Mappings предназначены контроля входных данных в определенном диапаоне.
Например, на джойстике MoveForward может зависеть от наклона контроллера (хотя на клавиатуре это только два значения: нажатие или отпускание кнопки).

В коде FPSCharacter.h:

	// Handles input for moving forward and backward.
	UFUNCTION()
		void MoveForward(float Value);

	// Handles input for moving right and left.
	UFUNCTION()
		void MoveRight(float Value);

	// Handles Yaw camera rotation.
	UFUNCTION()
		void TurnYaw(float Value);

	// Handles Pitch camera rotation.
	UFUNCTION()
		void LookPitch(float Value);

В коде FPSCharacter.cpp:

// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// Set up "movement" bindings.
	PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);

	// Set up "look" bindings.
	PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::TurnYaw);
	PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::LookPitch);
}

void AFPSCharacter::TurnYaw(float Value)
{
	if (Value != 0.f && Controller && Controller->IsLocalPlayerController())
	{
		APlayerController* const PC = CastChecked<APlayerController>(Controller);
		PC->AddYawInput(Value);
	}
}

void AFPSCharacter::LookPitch(float Value)
{
	if (Value != 0.f && Controller && Controller->IsLocalPlayerController())
	{
		APlayerController* const PC = CastChecked<APlayerController>(Controller);
		PC->AddPitchInput(Value);
	}
}

void AFPSCharacter::MoveForward(float Value)
{
	// Find out which way is "forward" and record that the player wants to move that way.
	FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::X);
	AddMovementInput(Direction, Value);
}

void AFPSCharacter::MoveRight(float Value)
{
	// Find out which way is "right" and record that the player wants to move that way.
	FVector Direction = FRotationMatrix(Controller->GetControlRotation()).GetScaledAxis(EAxis::Y);
	AddMovementInput(Direction, Value);
}

Сохраняем все, Компилируем код.
При запуске игры игрок должен уметь двигаться и вращать камерой.

Action Mappings

Action Mappings используются для срабатывания дискретных событий влияющих на игровое поведение.
Action Mappings предназначены контроля нажатий и отпускания кнопок.
Подробнее про Action Mappings и Axis Mappings: https://www.unrealengine.com/blog/input-action-and-axis-mappings-in-ue4

Добавим игроку возможность прыгать через Action Mappings в Project Settings -> Input.
Jump

  • Space Bar

https://docs.unrealengine.com/latest/images/Programming/Tutorials/FirstPersonShooter/2/5/JumpActionMapping_SpaceBar.jpg

В FPSCharacter.h:

// Sets jump flag when key is pressed.
UFUNCTION()
void StartJump();

// Clears jump flag when key is released.
UFUNCTION()
void StopJump();

В FPSCharacter.cpp:

// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// Set up "movement" bindings.
	PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);

	// Set up "look" bindings.
	PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::TurnYaw);
	PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::LookPitch);

	// Set up "action" bindings.
	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);
}

void AFPSCharacter::StartJump()
{
    bPressedJump = true;
}

void AFPSCharacter::StopJump()
{
    bPressedJump = false;
}

Сохраняем все, Компилируем код.

Skeletal Mesh

Скачиваем 3D модельку игрока https://docs.unrealengine.com/latest/attachments/Programming/Tutorials/FirstPersonShooter/2/6/GenericMale.zip
Создаем папку ProjectContent/Models/Characters/GenericMale и в нее импортируем fbx модельку.
В BP_FPSCharacter выбираем компонент Mesh
Устанавливаем Skeletal mesh в GenericMale.
Устанавливаем Location в (0;0;-88)
Mesh Compile, Save.

Запустите игру в editor's viewport и нажмите F8 чтобы перейти в режим свободной камеры и увидеть 3D модельку со стороны.

В FPSCharacter.h:

// FPS camera.
UPROPERTY(VisibleAnywhere)
UCameraComponent* FPSCameraComponent;

В FPSCharacter.cpp:

// Sets default values
AFPSCharacter::AFPSCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Create a first person camera component.
	FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
	// Attach the camera component to our capsule component.
	FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
	// Position the camera slightly above the eyes.
	FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
	// Allow the pawn to control camera rotation.
	FPSCameraComponent->bUsePawnControlRotation = true;

}

Камера теперь должна быть немного выше модели головы игрока.

First Person Character Mesh

Добавим модель рук игрока для режима игры от первого лица.

В FPSCharacter.h:

// First-person mesh (arms), visible only to the owning player.
UPROPERTY(VisibleDefaultsOnly, Category = Mesh)
USkeletalMeshComponent* FPSMesh;

FPSCharacter.cpp:

// Sets default values
AFPSCharacter::AFPSCharacter()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Create a first person camera component.
	FPSCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
	// Attach the camera component to our capsule component.
	FPSCameraComponent->SetupAttachment(GetCapsuleComponent());
	// Position the camera slightly above the eyes.
	FPSCameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, 50.0f + BaseEyeHeight));
	// Allow the pawn to control camera rotation.
	FPSCameraComponent->bUsePawnControlRotation = true;

	// Create a first person mesh component for the owning player.
	FPSMesh = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("FirstPersonMesh"));
	// Only the owning player sees this mesh.
	FPSMesh->SetOnlyOwnerSee(true);
	// Attach the FPS mesh to the FPS camera.
	FPSMesh->SetupAttachment(FPSCameraComponent);
	// Disable some environmental shadowing to preserve the illusion of having a single mesh.
	FPSMesh->bCastDynamicShadow = false;
	FPSMesh->CastShadow = false;

	// The owning player doesn't see the regular (third-person) body mesh.
	GetMesh()->SetOwnerNoSee(true);
}

Скомпилируйте код.

Скачайте https://docs.unrealengine.com/latest/attachments/Programming/Tutorials/FirstPersonShooter/2/8/HeroFPP.zip

Импортируйте модель HeroFPP в папку /Game/ProjectContent/Models/Characters/GenericMale
В компоненте FPSMesh внутри BP_FPSCharacter
Установите Location в {240, 0, 35} и Rotation в {-180, 50, -180}.
Нажмите Compile и Save.

Projectiles

Добавим игроку возможность стрелять в Project Settings -> Input.
Fire

  • Left Mouse Button

Fire

Создадим новый класс:
New C++ Class -> Выбираем родительский класс Actor и называем FPSProjectile.

В FPSProjectile.h:

	// Function that initializes the projectile's velocity in the shoot direction.
	void FireInDirection(const FVector& ShootDirection);

	// Sphere collision component.
	UPROPERTY(VisibleDefaultsOnly, Category = Projectile)
		USphereComponent* CollisionComponent;

	// Projectile movement component.
	UPROPERTY(VisibleAnywhere, Category = Movement)
		UProjectileMovementComponent* ProjectileMovementComponent;

В FPSProjectile.cpp:

// Sets default values
AFPSProjectile::AFPSProjectile()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Use a sphere as a simple collision representation.
	CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
	// Set the sphere's collision radius.
	CollisionComponent->InitSphereRadius(15.0f);
	// Set the root component to be the collision component.
	RootComponent = CollisionComponent;

	// Use this component to drive this projectile's movement.
	ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent"));
	ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent);
	ProjectileMovementComponent->InitialSpeed = 3000.0f;
	ProjectileMovementComponent->MaxSpeed = 3000.0f;
	ProjectileMovementComponent->bRotationFollowsVelocity = true;
	ProjectileMovementComponent->bShouldBounce = true;
	ProjectileMovementComponent->Bounciness = 0.3f;
}

// Function that initializes the projectile's velocity in the shoot direction.
void AFPSProjectile::FireInDirection(const FVector& ShootDirection)
{
	ProjectileMovementComponent->Velocity = ShootDirection * ProjectileMovementComponent->InitialSpeed;
}

В FPSCharacter.h:

	// Function that handles firing projectiles.
	UFUNCTION()
		void Fire();

	// Gun muzzle's offset from the camera location.
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Gameplay)
		FVector MuzzleOffset;

	// Projectile class to spawn.
	UPROPERTY(EditDefaultsOnly, Category = Projectile)
		TSubclassOf<class AFPSProjectile> ProjectileClass;

В начале FPSCharacter.cpp подключаем:

#include "FPSProjectile.h"

В FPSCharacter.cpp добавляем:

// Called to bind functionality to input
void AFPSCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	// Set up "movement" bindings.
	PlayerInputComponent->BindAxis("MoveForward", this, &AFPSCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &AFPSCharacter::MoveRight);

	// Set up "look" bindings.
	PlayerInputComponent->BindAxis("Turn", this, &AFPSCharacter::TurnYaw);
	PlayerInputComponent->BindAxis("LookUp", this, &AFPSCharacter::LookPitch);

	// Set up "action" bindings.
	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AFPSCharacter::StartJump);
	PlayerInputComponent->BindAction("Jump", IE_Released, this, &AFPSCharacter::StopJump);

	PlayerInputComponent->BindAction("Fire", IE_Pressed, this, &AFPSCharacter::Fire);
}

void AFPSCharacter::Fire()
{
	// Attempt to fire a projectile.
	if (ProjectileClass)
	{
		// Get the camera transform.
		FVector CameraLocation;
		FRotator CameraRotation;
		GetActorEyesViewPoint(CameraLocation, CameraRotation);

		// Transform MuzzleOffset from camera space to world space.
		FVector MuzzleLocation = CameraLocation + FTransform(CameraRotation).TransformVector(MuzzleOffset);
		FRotator MuzzleRotation = CameraRotation;
		// Skew the aim to be slightly upwards.
		MuzzleRotation.Pitch += 10.0f;
		UWorld* World = GetWorld();
		if (World)
		{
			FActorSpawnParameters SpawnParams;
			SpawnParams.Owner = this;
			SpawnParams.Instigator = Instigator;
			// Spawn the projectile at the muzzle.
			AFPSProjectile* Projectile = World->SpawnActor<AFPSProjectile>(ProjectileClass, MuzzleLocation, MuzzleRotation, SpawnParams);
			if (Projectile)
			{
				// Set the projectile's initial trajectory.
				FVector LaunchDirection = MuzzleRotation.Vector();
				Projectile->FireInDirection(LaunchDirection);
			}
		}
	}
}

Компилируем код.

Скачиваем модельку снаряда https://docs.unrealengine.com/latest/attachments/Programming/Tutorials/FirstPersonShooter/3/2/Sphere.zip

Создаем папки ProjectContent/Models/Props/Projectile и импортируем Sphere.fbx
Создаем папку ProjectContent/Blueprints/Projectile и в ней создайте Blueprint Class с именем BP_FPSProjectile на осовании класса FPSProjectile.
Открываем BP_FPSProjectile и выбираем CollisionComponent. Через Add Component к нему добавляем компонент Static Mesh с названием ProjectileMeshComponent.
Устанавливаем в ProjectileMeshComponent пункт Static Mesh в Sphere.
Устанавливаем Scale в (0.09;0.09;0.09)
Устанавливаем Collision Presets в NoCollision поскольку для столкновений используется SphereComponent, а не Static Mesh.
Compile и Save.
Открываем BP_FPSCharacter. Включаем режим Class Defaults Mode т.е. Class Defaults.
Устанавливаем Projectile Class в BP_FPSProjectile
Устанавливаем MuzzleOffset в {100, 0, 0} чтобы сняряд появлялся перед камерой.
Compile и Save
При запуске игрок на ЛКМ должен стрелять снарядами.

Projectile Collision and Lifetime

В Project Settings -> Collision -> New Object Channel создаем "Projectile" с Default Response равным Block.
В Project Settings -> Collision внутри Preset нажимаем New с названием "Projectile". Устанавливаем Pawn в Overlap, а все остальное в Block. ObjectType ставим равным Projectile. CollisionEnabled ставим равным Collision Enabled (Query and Physics). Description можно поставить как "Projectile collision profile".

Добавляем в FPSProjectile.h:

// Function that is called when the projectile hits something.
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);

Добавляем в FPSProjectile.cpp:

// Sets default values
AFPSProjectile::AFPSProjectile()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Use a sphere as a simple collision representation.
	CollisionComponent = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComponent"));
	// Set the sphere's collision radius.
	CollisionComponent->InitSphereRadius(15.0f);

	CollisionComponent->BodyInstance.SetCollisionProfileName(TEXT("Projectile"));

	CollisionComponent->OnComponentHit.AddDynamic(this, &AFPSProjectile::OnHit);

	// Set the root component to be the collision component.
	RootComponent = CollisionComponent;

	// Use this component to drive this projectile's movement.
	ProjectileMovementComponent = CreateDefaultSubobject<UProjectileMovementComponent>(TEXT("ProjectileMovementComponent"));
	ProjectileMovementComponent->SetUpdatedComponent(CollisionComponent);
	ProjectileMovementComponent->InitialSpeed = 3000.0f;
	ProjectileMovementComponent->MaxSpeed = 3000.0f;
	ProjectileMovementComponent->bRotationFollowsVelocity = true;
	ProjectileMovementComponent->bShouldBounce = true;
	ProjectileMovementComponent->Bounciness = 0.3f;

	// Die after 3 seconds.
	InitialLifeSpan = 3.0f;
}

// Function that is called when the projectile hits something.
void AFPSProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit)
{
    if (OtherActor != this && OtherComponent->IsSimulatingPhysics())
    {
        OtherComponent->AddImpulseAtLocation(ProjectileMovementComponent->Velocity * 100.0f, Hit.ImpactPoint);
    }
}

SetCollisionProfileName устанавливает Collision Profile в созданный нми ранее. InitialLifeSpan ограничивает время существования снаряда 3 секундами.

Скомпилийте код.

Добавьте на сцену статичный меш, например, Floor и придайте ему форму куба. Во вкладке Physics меша включите Simulate Physics. Можете также включить Simulate Physics на стандартных объектах из начальной сцены со столом и двумя стульями.
Откройте BP_FPSProjectile и в режиме Class Defaults Mode и установите ProjectileMeshComponent в Collision Presets значение Collision равным Projectile.
Скомпилируйте и сохраните Blueprint.
Снаряд долен отскакивать от объектов, сдвигать их.

Уничтожаемые объекты, Fracture, Destructible Mesh

Выберите static mesh в редакторе и создайте на его основе destructible mesh.
Например, создадим на основе SM_Couch уничтожаемый меш SM_Couch_DM.
destructible
Откройте меш и нажмите Fracture Mesh
fracture

Voronoi ‘Cell Site Count’ регулирует число кусочков на которые разлетится объект.

Измените конструктор в FPSProjectile.cpp:

// Function that is called when the projectile hits something.
void AFPSProjectile::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit)
{
	if (OtherActor != this && OtherComponent->IsSimulatingPhysics())
	{
		OtherComponent->AddImpulseAtLocation(ProjectileMovementComponent->Velocity * 100.0f, Hit.ImpactPoint);
	}

	ADestructibleActor* pDestructible(Cast<ADestructibleActor>(OtherActor));
	if (OtherActor != this && pDestructible)
	{
		pDestructible->DestructibleComponent->ApplyRadiusDamage(1000.0f, pDestructible->GetActorLocation(), 100.0f, 500.0f, true);
		pDestructible->DestructibleComponent->ApplyDamage(1000.0f, pDestructible->GetActorLocation(), pDestructible->GetActorLocation(), 1.0f);
		pDestructible->DestructibleComponent->WakeAllRigidBodies();
		pDestructible->DestructibleComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
	}
}

ApplyRadiusDamage - Hurt locally authoritative actors within the radius. Will only hit components that block the Visibility channel. ApplyDamage - Hurts the specified actor with generic damage. Target is Gameplay Statics WakeAllRigidBodies - Ensure simulation is running for all bodies in this component. Target is Primitive Component SetCollisionEnabled(ECollisionEnabled::NoCollision) - отключает столкновения после разрушения объекта.

Скомпилируйте код, перетащите SM_Couch_DM в игру и выстрелите по нему, меш должен разлететься на кусочки.

Вы также можете удалить объект сразу или через некоторое время после разрушения:

pDestructible->Destroy(); // Мнгновенно уничтожает
pDestructible->SetLifeSpan(6); // Уничтожает с задержкой в 6 секунд

см. также:

Crosshair

Скачайте https://docs.unrealengine.com/latest/attachments/Programming/Tutorials/FirstPersonShooter/3/5/Crosshair_fps_tutorial.zip

Внимание: Если размер текстуры не является степенью 2 (NPOT) она не будет применен Texture Streaming или генерироваться mipmap.

Создайте папку ProjectContent\Textures\Crosshairs и импортируйте crosshair.TGA
Создайте через New C++ Class новый класс с родительским классом HUD и названием FPSHUD

Добавьте в FPSHUD.h:

		// This will be drawn at the center of the screen.
		UPROPERTY(EditDefaultsOnly)
		UTexture2D* CrosshairTexture;

		// Primary draw call for the HUD.
		virtual void DrawHUD() override;

Добавьте в FPSHUD.cpp:

void AFPSHUD::DrawHUD()
{
    Super::DrawHUD();

    if (CrosshairTexture)
    {
        // Find the center of our canvas.
        FVector2D Center(Canvas->ClipX * 0.5f, Canvas->ClipY * 0.5f);

        // Offset by half of the texture's dimensions so that the center of the texture aligns with the center of the Canvas.
        FVector2D CrossHairDrawPosition(Center.X - (CrosshairTexture->GetSurfaceWidth() * 0.5f), Center.Y - (CrosshairTexture->GetSurfaceHeight() * 0.5f));

        // Draw the crosshair at the centerpoint.
        FCanvasTileItem TileItem(CrossHairDrawPosition, CrosshairTexture->Resource, FLinearColor::White);
        TileItem.BlendMode = SE_BLEND_Translucent;
        Canvas->DrawItem(TileItem);
    }
}

Скомпилируйте код.

Создайте папку ProjectContent\Blueprints\HUD
Создайте Blueprint класс на основании FPSHUD (Create Blueprint class based on FPSHUD) и назовите его BP_FPSHUD, сохраните его в папке ProjectContent\Blueprints\HUD.
Откройте BP_FPSHUD и установите значение crosshair texture в crosshair.
Скомпилируйте и сохраните созданный Blueprint.
Project Settings -> Maps & Modes установите HUD в BP_FPSHUD

CrosshairsInGame

Character Animation

Скачайте анимации https://docs.unrealengine.com/latest/attachments/Programming/Tutorials/FirstPersonShooter/4/1/FPP_Animations.zip

  • FPP_Idle.FBX
  • FPP_JumpEnd.FBX
  • FPP_JumpLoop.FBX
  • FPP_JumpStart.FBX
  • FPP_Run.FBX

Создайте папку ProjectContent\Animations и импортируйте в нее анимации выбрав Skeleton равным HeroFPP_Skeleton (Используя Ctrl в проводнике можно выделить сразу несколько файлов для импорта и нажать Import All).

Подробнее про импортирование можно узнать на https://docs.unrealengine.com/latest/INT/Engine/Content/ImportingContent/

Сохраните все.

AddNewAnimBP

Используя Add New создайте Animation Blueprint с родительским классом AnimInstance и названием Arms_AnimBP.

CreateAnimBP

Откройте Arms_AnimBP и добавьте переменные IsRunning, IsFalling типа Boolean

AddingNewVariable

Откройте EventGraph.
Добавьте Event Blueprint Update Animation если он отсутствует.

EventBlueprintUpdateAnimationNode

Добавьте "Try Get Pawn Owner"

EventBlueprintUpdateAnimationNode

Добавьте "Cast to Character", "Get Character Movement", "Get Movement Mode", "Equal (Enum)", "Get Velocity", "Vector Length". Если не находит по названию, то измените галочку Context Sensetive. GetCharacterMovementNode

Соедините их как на фото:
CompleteEventGraph

Установите после сединения Equal (Enum) в Falling.
Зажав Alt и перетащив IsFalling на graph создайте Set Is Falling.

IsFalling

ConnectedIsFalling
Используя поиск по символу > выберите float > float

GreaterThan

Зажав Alt и перетащив IsRunning на graph создайте Set Is Running.

CompleteEventGraph
Откройте AnimGraph.

Добавьте State Machine: State Machines > Add New State Machine с названием "Arms State Machine" и соедините как на фото:
ConnectedArmsStateMachine

Нажмите дважды на "Arms State Machine" для редактирования его графа.

Нажмите Add State.

Добавьте пять State:

  • Idle
  • Run
  • JumpStart
  • JumpEnd
  • JumpLoop

AnimationSMGraph

Нажмите дважды на Idle для редактирования его графа.

Добавьте "Play FPP_Idle" и соедините как на фото:

ConnectedIdleNode

Аналогично добавьте для Run "Play FPP_Run". Аналогично добавьте для оставшихся State соответствующий Play.

JumpEndtoIdle

Соедините Entry, Idle и Run как на фото:

WireIdletoRun

Дважды нажмите на транзакции (стрелка) от Idle до Run.

Зажав Ctrl и перетащив IsRunning на graph создайте Get Is Running и соедините как на фото:

IsRunningtoResult

Аналогично соедините от Run до Idle и откройте созданую транзакцию.

WireRuntoIdle

Аналогично перетащите Get Is Running.
Добавьте Not Boolean и соедините как на фото:

IsNotRunningtoResult

Добавьте транзацию от Idle до JumpStart и откройте ее.

Аналогично перетащите IsFalling и соедините как на фото:

IsFallingtoResult

Добавьте транзацию от Run до JumpStart и откройте ее.

Аналогично перетащите IsFalling и соедините как на фото:

IsFallingtoResult
Добавьте транзацию от JumpStart до JumpLoop и откройте ее.

Добавьте "Time Remaining" и "<=" типа float с значением 0.1.

Соедините как на фото:

TimeRemaining

Добавьте транзацию от JumpLoop до JumpEnd и откройте ее.

Добавьте "Get Is Falling" и "Not Boolean".

Соедините как на фото:

IsNotFalling

Добавьте транзацию от JumpEnd до Idle и откройте ее.

Добавьте TimeRemaining для 'FPP_JumpEnd' и <= типа float со значением 0.1.

Соедините как на фото:

TimeRemaining

Скомпилируйте и сохраните Arms_AnimBP.

JumpEndtoIdle

Откройте BP_FPSCharacter и выберите FPSMesh установив его AnimationBlueprint в Arms_AnimBP.

В режиме Defaults измените:

  • Location в {50, -15, -150}
  • Rotation в {0, 25, 350}.

NewArmTransform

Compile и save.

Запустите игру и сравните анимации в зависимости от движения персонажа.

Бег (Sprint)

Добавим игроку возможность бегать через Action Mappings в Project Settings -> Input.
Sprint

  • Left Shift

В конструкторе FPS_Character.h добавляем:

	UPROPERTY(EditAnyWhere)
		float RunSpeed = 800.0f;

	UPROPERTY(EditAnyWhere)
		float WalkSpeed = 250.0f;
		
	UFUNCTION()
		void StartSprint();

	UFUNCTION()
		void StopSprint();

В конструкторе FPS_Character.cpp добавляем:

	PlayerInputComponent->BindAction("Sprint", IE_Pressed, this, &AFPSCharacter::StartSprint);
	PlayerInputComponent->BindAction("Sprint", IE_Released, this, &AFPSCharacter::StopSprint);
	
	GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;

Также в FPS_Character.cpp добавляем функции:

void AFPSCharacter::StartSprint()
{
	GetCharacterMovement()->MaxWalkSpeed = RunSpeed;
}

void AFPSCharacter::StopSprint()
{
	GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
}

см. также:

@derofim
Copy link
Author

derofim commented May 1, 2017

image
image
image
image
image
image

@derofim
Copy link
Author

derofim commented May 1, 2017

image
image
image
image
image
image

@derofim
Copy link
Author

derofim commented May 1, 2017

image
image
image
image
image
image
image
image
image

@derofim
Copy link
Author

derofim commented May 1, 2017

image
image

@derofim
Copy link
Author

derofim commented May 1, 2017

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment