WordPress搭建手机网站,青海公司网站建设哪家快,开发网上商城公司,网站建设公司企业网站管理系统虚幻5.2.1探索
项目目录探索
C工程一定不能是中文路径#xff0c;中文项目名#xff0c;最好全部不要用中文#xff0c;蓝图项目可以是中文浅浅创建一个空项目#xff0c;讲解一下之前UE4没有讲解的项目目录文件的分布组成 .vs#xff1a;文件夹一般是项目编译缓存文件夹…虚幻5.2.1探索
项目目录探索
C工程一定不能是中文路径中文项目名最好全部不要用中文蓝图项目可以是中文浅浅创建一个空项目讲解一下之前UE4没有讲解的项目目录文件的分布组成 .vs文件夹一般是项目编译缓存文件夹Binaries存储虚幻引擎二进制的针对不同平台发布的配置等Config虚幻的配置文件夹一般里面都是虚幻的配置或者自己写的配置Content内容文件夹一般开发者后续创建的资产都在这里面DerivedDataCache虚幻生成与管理派生数据的文件夹包含着色器的编译编译材质贴图等等Intermediate存储一些模型缓存图片缓存等等这个一般我们是不需要管理的一般编译器出问题要删除C代码时这个文件也是要被删除的Saved包含配置文件快照日志文件那些Source代码存放的位置一般我们写C代码很容易导致编译器爆掉我们除了要删除相对的代码或者是代码文件还要删除.vs这个缓存文件夹和这三个BinariesIntermediate项目名.sln文件文件然后右键项目名.uproject文件里面会有重新构建项目的选项重新构建项目除错
虚幻C常用结构
虚幻引擎C类层级结构(Hierarchy)与UE4一样一样复习一下 反射与垃圾回收也是一样的使用宏进行标识UE的UHT系统会帮我们进行垃圾回收
创建Actor类
创建一个Actor类当在创建Actor类时如果添加了文件则代码里面会有这个添加了文件的头文件它会让编译器找不到Actor类UE4好像没有这种情况UE5就有我们删除这个文件就可以了 然后在UE5中vs中生成代码时记得要关闭热重载不然vs中的编译不会通过
渐渐来个Hellow World
给Actor来个Mesh打印一下Hellow World通过日志打印与屏幕打印打印到屏幕要加头文件#include Engine/Engine.h给Mesh硬编码加上材质与网格要加头文件#include UObject/ConstructorHelpers.h UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category Properties)class UStaticMeshComponent* StaticMesh;
//上面是.h中Public的内容-------------------------------------------------------------------------------------------------------#include MyActor_One.h
#include Engine/Engine.h
#include UObject/ConstructorHelpers.h
#include Components/StaticMeshComponent.h// Sets default values
AMyActor_One::AMyActor_One()
{// Set this actor to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick true;StaticMesh CreateDefaultSubobjectUStaticMeshComponent(TEXT(StaticMesh));RootComponent StaticMesh;//硬编码材质与网格ConstructorHelpers::FObjectFinderUStaticMesh StaticMeshAsset(TEXT(/Script/Engine.StaticMesh/Engine/BasicShapes/Sphere.Sphere));ConstructorHelpers::FObjectFinderUMaterialInterface MaterialAsset(TEXT(/Script/Engine.Material/Engine/BasicShapes/BasicShapeMaterial.BasicShapeMaterial));if (StaticMeshAsset.Succeeded() MaterialAsset.Succeeded()){StaticMesh-SetStaticMesh(StaticMeshAsset.Object);StaticMesh-SetMaterial(0, MaterialAsset.Object);}
}// Called when the game starts or when spawned
void AMyActor_One::BeginPlay()
{Super::BeginPlay();UE_LOG(LogTemp, Warning, TEXT(Hello World));UE_LOG(LogTemp, Warning, TEXT(Hello World));UE_LOG(LogTemp, Error, TEXT(Hello World));//这里的-1可以使用INDEX_NONEINDEX_NONE也是-1UE的宏GEngine-AddOnScreenDebugMessage(-1, 10.f, FColor::Red, FString::Printf(TEXT(Hello World)));} 运行结果
宏的参数讲解
变量的宏参数UPROPERTY() VisibleAnywhere在蓝图中与视口中都可见VisibleDefaultsOnly只在蓝图中可见VisibleInstanceOnly只在视口中可见EditAnywhere在蓝图中与视口中都可编辑EditDefultsOnly在蓝图中可编辑EditInstanceOnly在视口中可编辑BlueprintReadOnly在蓝图中可读BlueprintReadWrite在蓝图中可读可写Category标签meta (MakeEditWidget true)这是一个可选的元标记Metadata用于添加额外的属性信息。在这种情况下MakeEditWidget 被设置为 “true”这表示该属性可以在编辑器中作为一个小部件进行编辑。这通常用于自定义编辑器小部件以提供更直观的属性编辑体验。meta(ClampMin -10,ClampMax 10, UIMin -10, UIMax 10))clamp键盘输入值控制ui鼠标拉动值控制meta (AllowPrivateAccess true)可以让内部的其他成员访问 函数的宏参数UFUNCTION() BlueprintNativeEvent:BlueprintNativeEvent关键词允许在Unreal Engine蓝图中声明本地事件并通过C进行实现和扩展。在C中实现一个蓝图本地事件时需要在函数名后添加_Implementation作为后缀。这是为了区分虚函数和其实现函数并保持代码的一致性和清晰度总的来说就是会在C中提供一个默认的实现然后蓝图中去覆盖它改写它在蓝图中实现这个函数时如果调用一个父类的版本它会先调用C里面加了_Implementation这个函数然后再去做蓝图其他的操作BlueprintCallable允许函数在蓝图中进行调用BlueprintImplementableEvent会把函数变成一个事件把函数提升为事件后就不能去初始化函数了因为这个是在蓝图调用的事件Category标签
虚幻中的三维坐标
在数学三维直角坐标系中里面XYZ也可以是XRollYPitchZYaw这是右手坐标系在UE中面XYZ也可以是XPitchYYawZRoll这是左手坐标系UE中的在UE中XYZ轴的正向分别对应前方、右方和上方显示的箭头颜色分别为红色、绿色和蓝色三基色的习惯顺序。
虚幻5中的增强输入系统
UE5中已经摒弃掉了轴映射机制改用为增强输入系统UE5中没有默认开启增强输入系统我们需要添加这个模块在项目名.Build.cs里面这个完成后最好是删除那几个文件重新构建一下避免一下后续的bug项目目录探索那章
定义绑定映射系统与处理函数
增强输入系统的特定代码及定义一个映射绑定一个移动轴的绑定然后一个绑定的处理函数这个处理函数要传入FInputActionValue的结构体要添加头文件#include InputActionValue.h在当前.h文件中
public://映射绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputMappingContext* DefaultMappingContext;//移动绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputAction* MoveAction;protected:
void CharacterMove(const FInputActionValue value);这个处理函数基本就和之前写UE4时人物移动面向逻辑处理差不多
void AMyCharacter::CharacterMove(const FInputActionValue value)
{FVector2D MovementVector value.GetFVector2D();//获取速度if (Controller!nullptr){FRotator Rotation Controller-GetControlRotation();FRotator YawRotation FRotator(0, Rotation.Yaw, 0);//获取到前后单位向量FVector ForwardDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);//获取左右单位向量FVector RightDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);AddMovementInput(ForwardDirection, MovementVector.Y);AddMovementInput(RightDirection, MovementVector.X);}
}对比一下之前写的面向移动逻辑这是之前UE4写的面向逻辑 那就来浅浅解释一下虚幻5中为什么这样写逻辑 已知虚幻中的XPitchYYawZRoll 我们获取到FInputActionValue这个结构体中的FVector2D注意这里是FVector2D这是数学平面坐标系 FVector2D MovementVector value.GetFVector2D();//获取速度 而在UE三维移动中我们只需要关注Yaw(也就是Y) FRotator YawRotation FRotator(0, Rotation.Yaw, 0); 然后在虚幻中默认为右方向以角色右手为正方向所以那平面坐标系里面X是不是就是前后了Y是左右 FVector ForwardDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X); FVector RightDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y); 此时我们已经得到了前后左右的单位向量后回到开始的逻辑因为UE5增强输入系统传入的是FInputActionValue结构体了然后获取的是FVector2D这是个数学平面坐标系所以添加到角色移动中这里前后就是数学平面坐标系的Y了左右就是X了 AddMovementInput(ForwardDirection, MovementVector.Y); AddMovementInput(RightDirection, MovementVector.X);
绑定移动
在SetupPlayerInputComponen()中进行绑定移动我们需要将PlayerInputComponent转换为UEnhancedInputComponent然后进行绑定为了增强型输入系统这里需要头文件#include EnhancedInputComponent.h来使用UEnhancedInputComponent组件BindAction(MoveAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterMove); MoveAction之前定义的移动绑定UInputAction类ETriggerEvent::Triggered触发发生在一个或多个处理节拍之后一般用Triggered比较多其他不常用this自身来进行绑定AMyCharacter::CharacterMove处理函数
// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);UEnhancedInputComponent* EnhancedInputComponent CastUEnhancedInputComponent(PlayerInputComponent);if (EnhancedInputComponent){//移动绑定EnhancedInputComponent-BindAction(MoveAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterMove);}
}绑定映射
在BeginPlay()中绑定增强输入系统的映射首先将Controller转换为APlayerController成功后使用UEnhancedInputLocalPlayerSubsystem将本地玩家使用增强型输入系统需要使用头文件#include EnhancedInputSubsystems.h成功后就绑定映射
// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{Super::BeginPlay();APlayerController* PlayerController CastAPlayerController(Controller);if (PlayerController){UEnhancedInputLocalPlayerSubsystem* Subsystem ULocalPlayer::GetSubsystemUEnhancedInputLocalPlayerSubsystem(PlayerController-GetLocalPlayer());if (Subsystem){//映射到上下文Subsystem-AddMappingContext(DefaultMappingContext, 0);}}
}编辑器操作
创建一个输入操作蓝图与一个输入映射场景蓝图 将输入操作的值类型变更为Axis2D也就是Vector2D因为我们角色是在平面上移动 在输入映射中添加映射注意在虚幻中我们的轴默认是朝着右方向的以角色的右手边为正方向所以定义W向前的时候修改器要添加个拌合输入轴值将右正方向旋转到向前的正方向 S向后的修改器添加个拌合输入轴值然后添加个否定(反向) D方向是朝右的就不需要做任何修改A方向就添加个否定即可 然后在角色蓝图中添加上增强输入系统
视角移动绑定
再添加一个UInputAction用来绑定视角和视角处理函数 //视角绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputAction* LookAction;void CharacterLook(const FInputActionValue value);视角处理函数
void AMyCharacter::CharacterLook(const FInputActionValue value)
{FVector2D LookAxisVector value.GetFVector2D();if (Controller ! nullptr){AddControllerPitchInput(LookAxisVector.Y);AddControllerYawInput(LookAxisVector.X);}
}// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);UEnhancedInputComponent* EnhancedInputComponent CastUEnhancedInputComponent(PlayerInputComponent);if (EnhancedInputComponent){//移动绑定EnhancedInputComponent-BindAction(MoveAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterMove);EnhancedInputComponent-BindAction(LookAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterLook);}
}再建一个输入蓝图依然是FVector2D 添加到映射集合中注意游戏中的视角是反向的要修改为否定只开启Y方向
运行结果 限制上下视角范围
限制角色上下视角范围和虚幻4中的写法差不多只不过值变为了FInputActionValue结构体中的FVector2D 二维向量
void AMyCharacter::CharacterLook(const FInputActionValue value)
{FVector2D LookAxisVector value.GetFVector2D();if (Controller ! nullptr){GEngine-AddOnScreenDebugMessage(1, 10, FColor::Red, FString::Printf(TEXT(%f),(GetControlRotation().Pitch)));AddControllerYawInput(LookAxisVector.X);if (GetControlRotation().Pitch 270.f GetControlRotation().Pitch180.f LookAxisVector.Y 0.f){return;}if (GetControlRotation().Pitch 180.f GetControlRotation().Pitch45.f LookAxisVector.Y 0.f){return;}AddControllerPitchInput(LookAxisVector.Y);}
}MyCharacter.h
// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include CoreMinimal.h
#include GameFramework/Character.h
#include InputActionValue.h
#include MyCharacter.generated.hUCLASS()
class MYOBJECTUE5_API AMyCharacter : public ACharacter
{GENERATED_BODY()public:// Sets default values for this characters propertiesAMyCharacter();UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category Camera, meta (AllPrivateAccess true))class USpringArmComponent* SpringArm;UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category Camera, meta (AllPrivateAccess true))class UCameraComponent* MyCamera;//映射绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputMappingContext* DefaultMappingContext;//移动绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputAction* MoveAction;//视角绑定UPROPERTY(EditAnywhere, BlueprintReadOnly, Category Input, meta (AllPrivateAccess true))class UInputAction* LookAction;protected:// Called when the game starts or when spawnedvirtual void BeginPlay() override;void CharacterMove(const FInputActionValue value);void CharacterLook(const FInputActionValue value);public: // Called every framevirtual void Tick(float DeltaTime) override;// Called to bind functionality to inputvirtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;};
MyCharacter.cpp
// Fill out your copyright notice in the Description page of Project Settings.#include MyCharacter.h
#include Camera/CameraComponent.h
#include GameFramework/SpringArmComponent.h
#include GameFramework/CharacterMovementComponent.h
#include EnhancedInputComponent.h
#include EnhancedInputSubsystems.h
#include Engine/Engine.h
// Sets default values
AMyCharacter::AMyCharacter()
{// Set this character to call Tick() every frame. You can turn this off to improve performance if you dont need it.PrimaryActorTick.bCanEverTick true;GetCharacterMovement()-bOrientRotationToMovement true;GetCharacterMovement()-RotationRate FRotator(0.f, 500.f, 0.f);GetCharacterMovement()-MaxWalkSpeed 500.f;GetCharacterMovement()-MinAnalogWalkSpeed 20.f;GetCharacterMovement()-BrakingDecelerationWalking 2000.f;//相机臂SpringArm CreateDefaultSubobjectUSpringArmComponent(TEXT(SpringArm));SpringArm-SetupAttachment(GetRootComponent());SpringArm-TargetArmLength 400.f;SpringArm-bUsePawnControlRotation true;//相机MyCamera CreateDefaultSubobjectUCameraComponent(TEXT(MyCamera));MyCamera-SetupAttachment(SpringArm, USpringArmComponent::SocketName);//附加到末尾MyCamera-bUsePawnControlRotation false;
}// Called when the game starts or when spawned
void AMyCharacter::BeginPlay()
{Super::BeginPlay();APlayerController* PlayerController CastAPlayerController(Controller);if (PlayerController){UEnhancedInputLocalPlayerSubsystem* Subsystem ULocalPlayer::GetSubsystemUEnhancedInputLocalPlayerSubsystem(PlayerController-GetLocalPlayer());if (Subsystem){//映射到上下文Subsystem-AddMappingContext(DefaultMappingContext, 0);}}
}void AMyCharacter::CharacterMove(const FInputActionValue value)
{FVector2D MovementVector value.GetFVector2D();//获取速度if (Controller!nullptr){FRotator Rotation Controller-GetControlRotation();FRotator YawRotation FRotator(0, Rotation.Yaw, 0);//获取到前后单位向量FVector ForwardDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);//获取左右单位向量FVector RightDirection FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);AddMovementInput(ForwardDirection, MovementVector.Y);AddMovementInput(RightDirection, MovementVector.X);}
}void AMyCharacter::CharacterLook(const FInputActionValue value)
{FVector2D LookAxisVector value.GetFVector2D();if (Controller ! nullptr){GEngine-AddOnScreenDebugMessage(1, 10, FColor::Red, FString::Printf(TEXT(%f),(GetControlRotation().Pitch)));AddControllerYawInput(LookAxisVector.X);if (GetControlRotation().Pitch 270.f GetControlRotation().Pitch180.f LookAxisVector.Y 0.f){return;}if (GetControlRotation().Pitch 180.f GetControlRotation().Pitch45.f LookAxisVector.Y 0.f){return;}AddControllerPitchInput(LookAxisVector.Y);}
}// Called every frame
void AMyCharacter::Tick(float DeltaTime)
{Super::Tick(DeltaTime);}// Called to bind functionality to input
void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{Super::SetupPlayerInputComponent(PlayerInputComponent);UEnhancedInputComponent* EnhancedInputComponent CastUEnhancedInputComponent(PlayerInputComponent);if (EnhancedInputComponent){//移动绑定EnhancedInputComponent-BindAction(MoveAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterMove);EnhancedInputComponent-BindAction(LookAction, ETriggerEvent::Triggered, this, AMyCharacter::CharacterLook);}
}