mini: false, //迷你模式 autoplay: false, //自动播放 theme: '#FADFA3', //主题色 loop: 'all', //音频循环播放, 可选值: 'all'全部循环, 'one'单曲循环, 'none'不循环 order: 'random', //音频循环顺序, 可选值: 'list'列表循环, 'random'随机循环 preload: 'auto', //预加载,可选值: 'none', 'metadata', 'auto' volume: 0.7, //默认音量,请注意播放器会记忆用户设置,用户手动设置音量后默认音量即失效 mutex: true, //互斥,阻止多个播放器同时播放,当前播放器播放时暂停其他播放器 listFolded: false, //列表默认折叠 listMaxHeight: 90, //列表最大高度 lrcType: 3, //歌词传递方式

Based UE_Project Notes

设置版本控制

Youtube视频

虚幻打包

将下面3个文件删除

打包之前先热重载并运行一下
打包到一个空文件夹中

Bookmarks

书签功能:标记特定位置,快速跳转到之前标记的位置

  • 添加书签:选择你想要标记的位置,然后使用快捷键(Ctrl + 1到Ctrl + 9)来添加书签
  • 跳转到书签:使用相应的快捷键(1到9)可以快速跳转到已设置的书签位置
  • 管理书签:在视角中,可以找到书签管理器,允许查看和删除现有书签。

显示帧率

快捷键:Ctr+Shift+H

游戏视角

快捷键:G

全屏模式

快捷键:F11

高分辨率截图

落地快捷键

快捷键:End

光照

DirectionalLight(定向光源):类似平行光

  • 可以通过设置Rotation来调整光源
  • 将定向光照设置为moveable
  • 可以最多使用两个定向光源,为每个定向光源设置大气太阳光照指数(Atmosphere Sun Light Index)
    例如,0表示太阳,1代表月亮
  • 使用 Ctrl + L 并移动鼠标将调整已设为指数0的定向光源。它通常是太阳
  • 使用 Ctrl + L + Shift 并移动鼠标将调整已设为指数1的定向光源。它通常是月亮

定向光源可以打开温度选项设置太阳的温度

开启丁达尔效应:

SkyAtmosphere(天空大气):蓝天

VolumetricCloud(体积云):云彩效果

SkyLight(天空光照):阴影光照

  • 将天空光照设置为moveable
  • 实时捕捉进行动态一天中的时间模拟

ExponentialHeightFog(指数级高度雾):

地形

创建地形时可以选择大小,不要过大

快捷键:Shift+1,Shift+2...

注意:若地形无法显示,打开'World Partition'****左键选择或自定义框取区域右键选择分区加载地图

  • Sculpt:
    鼠标左键: 升高地形
    鼠标左键 + Shift: 降低地形

材质

  • 添加材质:

  • 通过Bridge获取材质:

  • 将材质设置为rough使得材质不会反光

  • LandscapeLayerBlend:图层混合

    添加6个元素并命名:

    将Bridge中获得的材质的第一个纹理拖到M_Landscape材质中并连接BaseColor


    将第二个纹理以相同的顺序拖到M_Landscape材质中并连接Normal


    将材质添加到Landscape中

    地形图层混合:使用Paint来绘制,使用Weight-Blended Layer (normal)允许多个层的叠加,能够实现精细的渐变效果,用于创建复杂的地形和表面的自然过渡,Non Weight-Blended Layer类似于雪覆盖在地上

    更改材质颜色:

    绘制地形:

绘制草木

选择Foliage Mode里的Paint来绘制

动态小草:开启Wind

垂直的树木:关闭Align to Normal

设置树木碰撞:

提高帧率


PostProcessVolume(后期处理体积)

  • 为整个场景或特定区域应用各种视觉效果
  • 开启全地图包含:
  • 调节色温:
  • 调节Bloom(光晕):
  • 调节最大最小光照:
  • 调节饱和、对比、伽马值等


打包关卡演员

将多个元素合并为一个演员

创建一个Level:可以将资产里的Level导入


将Level中的资产分离,便于操作

可以从官方案例里添加Actor到Mylevel中

设置纹理采样源

使纹理加载更快捷

启用虚拟纹理支持

设置Visual Studio

【002 Setting up Visual Studio】
https://www.bilibili.com/video/BV1Hi22YZEqt?vd_source=78f7f9f8d415f8df9a79d831bb4f277c

虚幻中的继承关系

创建C++类


创建蓝图类

新建两个文件夹,Blueprints和Items用于存放蓝图


蓝图中打印字符串

  • Print String:在屏幕和日志中均显示
  • Log String:仅在日志中显示
  • Duration:屏幕字符显示持续时间


  • 先打印的字符串在下面:
  • Key值:两个Print String节点使用相同的Key值时,后一个节点的消息会替换前一个节点的消息
    只打印了第二条消息
  • 在Tick中打印时:
  • 在Tick中打印并设置Key值时:后一个值会替换前一个值
    因为Delta Time为字符串,不会发生变化,所以屏幕上的值不变

    将Delta Seconds打印到屏幕可以发现屏幕上的值在变化

C++中打印字符串

①UE_LOG():将字符输出到日志
Log , Warning , Error:

UE_LOG(LogTemp, Log, TEXT("BeginPlay called!"));
UE_LOG(LogTemp, Warning, TEXT("BeginPlay called!"));
UE_LOG(LogTemp, Error, TEXT("BeginPlay called!"));



在TEXT中使用%s,%d:

FString name = "Sam";
UE_LOG(LogTemp, Log, TEXT("Name:%s"), *name);
UE_LOG(LogTemp, Log, TEXT("%d"),10);



②GEngine->AddOnScreenDebugMessage():将字符打印到屏幕
函数原型:


使用实例:

if(GEngine)
{
	GEngine->AddOnScreenDebugMessage(1, 60.f, FColor::Blue, FString("Print to the screen"));
}



if(GEngine)
{
	FString Message = FString::Printf(TEXT("DeltaTime:%f"), DeltaTime);
	GEngine->AddOnScreenDebugMessage(2, 30.f, FColor::Cyan, Message);
}


GetName()

获取当前物体名称

if(GEngine)
{
	FString Name = GetName();
	FString Message = FString::Printf(TEXT("Name:%s"),*Name);
	GEngine->AddOnScreenDebugMessage(2, 30.f, FColor::Cyan, Message);
}


GetActorLocation()

获取当前actor的位置

FVector Location = GetActorLocation();

ToString()

将FVector,FRotator类转为字符串

FVector Location = GetActorLocation();
UE_LOG(LogTemp, Warning, TEXT("Location:%s"), *Location.ToString());


DrawDebugSphere()

绘制调试球体

函数原型:

void DrawDebugSphere(  
    UWorld* World,  
    const FVector& Center,  
    float Radius,  
    int32 Segments,  
    FColor Color,  
    bool bPersistentLines,  
    float LifeTime,  
    uint8 DepthPriority,  
    float Thickness  
);  


使用实例:

DrawDebugSphere(GetWorld(), GetActorLocation(), 20.f, 40, FColor::Red, false, 30.f);


GetActorForwardVector()

这个向量是单位向量,表示 actor 的前方在世界坐标系中的方向

FVector Forward = GetActorForwardVector();

DrawDebugLine()

绘制调试线条

函数原型:

void DrawDebugLine(  
    UWorld* World,  
    const FVector& Start,  
    const FVector& End,  
    FColor Color,  
    bool bPersistentLines,  
    float LifeTime,  
    uint8 DepthPriority,//深度优先级,值越小优先级越高(默认值通常是 0)
    float Thickness//绘制线条的厚度
);  


函数实例:

//从当前 actor 位置向前延伸 100 单位的红色线条
DrawDebugLine(GetWorld(), GetActorLocation(), GetActorLocation() + GetActorForwardVector() * 100, FColor::Red, true);

DrawDebugPoint()

绘制调试点

函数原型:

void DrawDebugPoint(
    UWorld* World, 
    FVector const& Location, 
    float Size, 
    FColor Color, 
    bool bPersistentLines = false, 
    float Lifespan = 0.0f, 
    uint8 DepthPriority = 0
);


函数实例:

DrawDebugPoint(GetWorld(), GetActorLocation(), 20, FColor::Blue, false, 60.f);

宏定义

在Source文件夹下的Slash中添加新的头文件DebugMacros

#define DRAW_SPHERE(Location) if(GetWorld()) DrawDebugSphere(GetWorld(),Location,20.f,20,FColor::Red,true);
#define DRAW_LINE(StartLocation,EndLocation) if(GetWorld()) DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, true, -1, 0, 1);
#define DRAW_POINT(Location) if(GetWorld()) DrawDebugPoint(GetWorld(), Location, 20, FColor::Blue, false, 60.f);
#define DRAW_VECTOR(StartLocation,EndLocation) if(GetWorld())\
{\
	DrawDebugLine(GetWorld(), StartLocation, EndLocation, FColor::Red, true, -1, 0, 1);\
	DrawDebugPoint(GetWorld(), EndLocation, 20, FColor::Blue, false, 60.f);\
}


在Item.cpp中包含头文件

DRAW_SPHERE(GetActorLocation());
//DRAW_LINE(GetActorLocation(), GetActorLocation() + GetActorForwardVector() * 100);
//DRAW_POINT(GetActorLocation());
DRAW_VECTOR(GetActorLocation(), GetActorLocation() + GetActorForwardVector() * 100);

SetActorLocation()

设置Actor位置

函数原型:

void SetActorLocation(
    const FVector& NewLocation,//要设置的新位置,通常是一个三维向量(X, Y, Z)
    bool bSweep = false,//指定是否在移动 Actor 时进行碰撞检测。如果为 true,则会检测移动路径上的任何碰撞,并在碰撞发生时返回一个 FHitResult 
    FHitResult* OutHit = nullptr, //如果 bSweep 为 true,可以传递一个指向 FHitResult 对象的指针,以获取碰撞信息,包括碰撞的物体、碰撞点等
    ETeleportType Teleport = ETeleportType::None//指定移动的类型(如瞬移、逐步移动等)
);

函数实例:

SetActorLocation(FVector(0.f, 0.f, 50.f));

SetActorRotation()

设置Actor旋转

函数原型:

void SetActorRotation(
    const FRotator& NewRotation,//要设置的新旋转,通常是一个三维向量(X, Y, Z)
    bool bSweep = false, //指定是否在移动 Actor 时进行碰撞检测。如果为 true,则会检测移动路径上的任何碰撞,并在碰撞发生时返回一个 FHitResult 
    FHitResult* OutHit = nullptr,//如果 bSweep 为 true,可以传递一个指向 FHitResult 对象的指针,以获取碰撞信息,包括碰撞的物体、碰撞点等
    ETeleportType Teleport = ETeleportType::None//指定移动的类型(如瞬移、逐步移动等)
);

函数实例:

SetActorRotation(FRotator(0.f, 45.f, 0.f));


Pitch:沿Y轴旋转
Yaw:沿Z轴旋转
Roll:沿X轴旋转

设置固定帧率

AddActorWorldOffset()

通过增加世界坐标偏移量从而进行移动

函数原型:

AddActorWorldOffset(
    FVector DeltaLocation, 
    bool bSweep = false, 
    FHitResult* Hit = nullptr, 
    ETeleportType Teleport = ETeleportType::None
);

函数实例:

float MovementRate = 100.f;//速度
AddActorWorldOffset(FVector(0, 0, MovementRate * DeltaTime));//速度*每帧的时间间隔
DrawDebugSphere(GetWorld(), GetActorLocation(), 10, 20, FColor::Red, false, -1);

AddActorWorldRotation()

以世界坐标系的方式,给Actor添加一个旋转增量

函数原型:

void AddActorWorldRotation(
    FRotator DeltaRotation, 
    bool bSweep = false, 
    FHitResult* Hit = nullptr, 
    ETeleportType Teleport = ETeleportType::None
);

函数实例:

float RotationRate = 100.f;//速度
AddActorWorldRotation(FRotator(0.f, RotationRate * DeltaTime, 0.f));//速度*每帧的时间间隔

DrawDebugSphere(GetWorld(), GetActorLocation(), 10, 20, FColor::Red, false, -1);
DrawDebugLine(GetWorld(), GetActorLocation(), GetActorLocation() + GetActorForwardVector() * 100.f, FColor::Red, false, -1);

三角函数

使Actor以正弦函数上下摆动

RunningTime += DeltaTime;
AddActorWorldOffset(FVector(0.f, 0.f,FMath::Sin(RunningTime*10)*0.4));


UPROPERTY()

  • VisibleAnywhere:在默认蓝图和地图内的蓝图实例的详细信息面板中均可见
UPROPERTY(VisibleAnywhere)
int32 num = 10;
  • VisibleDefaultOnly:仅在默认蓝图的详细信息面板中可见
UPROPERTY(VisibleDefaultsOnly)
int32 num = 10;
  • VisibleInstanceOnly:仅在蓝图实例的详细信息面板中可见
UPROPERTY(VisibleInstanceOnly)
int32 num = 10;

  • EditAnyWhere:在默认蓝图和地图内的蓝图实例的详细信息面板中均可编辑
UPROPERTY(EditAnyWhere)
int32 num = 10;
  • EditDefaultOnly:仅在默认蓝图的详细信息面板中可编辑
UPROPERTY(EditDefaultOnly)
int32 num = 10;
  • EditInstanceOnly:仅在蓝图实例的详细信息面板中可编辑
UPROPERTY(EditInstanceOnly)
int32 num = 10;

  • BlueprintReadWrite:在蓝图面板中可'get'和'set'
UPROPERTY(BlueprintReadWrite)
int32 num = 10;
  • BlueprintReadOnly:仅在蓝图面板中可'get'
UPROPERTY(BlueprintReadWrite)
int32 num = 10;

注:蓝图属性只能在public中使用,若想在private中使用,需要如下操作

UPROPERTY(BlueprintReadWrite, meta = (AllowPrivateAccess = "true"));
int32 num = 10;

  • VisibleAnywhere+BlueprintReadWrite:在默认蓝图蓝图实例蓝图面板中均可编辑
UPROPERTY(EditAnywhere,BlueprintReadWrite)//用逗号分隔
int32 num = 10;
  • Category:将属性分类
UPROPERTY(EditAnywhere, Category = "MyVarieties")
int32 num1 = 5;

UPROPERTY(EditAnywhere, Category = "MyVarieties")
int32 num2 = 10;


UPROPERTY(EditAnywhere, Category = "MyVarieties|One")
int32 num1 = 5;

UPROPERTY(EditAnywhere, Category = "MyVarieties|One")
int32 num2 = 10;

UPROPERTY(EditAnywhere, Category = "MyVarieties|Two")
int32 num3 = 15;

  • Function

BlueprintPure:纯函数
BlueprintCallable:普通函数

UFUNCTION(BlueprintPure)//纯函数
float TransformedSin();

UFUNCTION(BlueprintCallable)//普通函数
float TransformedCosin();


默认蓝图资源:

蓝图实例:

蓝图面板:

模板函数

//.h
template<typename T>
T Avg(T first, T second);

template<typename T>
inline T AItem::Avg(T first, T second)
{
	return (first + second) / 2;
}


//.cpp
int32 AvgInt = Avg<int32>(3, 5);
UE_LOG(LogTemp, Warning, TEXT("Average:%d"), AvgInt);

FVector AvgVector = Avg<FVector>(GetActorLocation(), FVector::ZeroVector);
DRAW_POINT(AvgVector);

Component

  • UStaticMeshComponent(静态网络体组件):
    通常用于显示静态网格,可以将多个StaticMeshComponents组合到同一个Actor中
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* BaseMesh;//静态网络1

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UStaticMeshComponent* TurretMesh;//静态网络2
  • USceneComponent(场景组件):
    包含位置(Location)旋转(Rotation)缩放(Scale)属性,可以通过这些属性来定义组件在世界中的位置和方向。可以作为其他组件的父节点,形成一个组件层级结构
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AlloPrivateAccess = "true"))
USceneComponent* ProjectileSpawnPoint;//生成投射物
  • USkeletalMeshComponent(骨骼网格组件):
    用于显示可以进行骨骼动画的角色和生物
UPROPERTY(VisibleAnywhere)
USkeletalMeshComponent* BirdMesh;

  • UCapsuleComponent(碰撞体组件):
    用于处理角色和其他物体的碰撞和物理交互
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components", meta = (AllowPrivateAccess = "true"))
UCapsuleComponent* CapsuleComp;
  • RootComponent(根组件):
    根组件是一个Actor中的基础组件,所有其他组件都是这个组件的子组件。在虚幻引擎中,每个Actor都必须有一个根组件根组件可以是任何类型的组件(如UStaticMeshComponent、USkeletalMeshComponent、USceneComponent等)
CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider"));//创建碰撞体组件
RootComponent = CapsuleComp;//将碰撞体组件设置为根组件
  • USpringArmComponent(弹簧臂组件):
    相机组件附加到弹簧臂,使其跟随弹簧臂的移动,主要用于实现相机的跟随效果,将弹簧臂的目标设置为任何 Actor,使得相机能够跟随该目标
UPROPERTY(VisibleAnywhere, Category = "Components")
USpringArmComponent* SpringArm;
  • UCameraComponent(相机组件):
    通常将相机组件附加到 USpringArmComponent,以实现平滑的相机跟随效果
UPROPERTY(VisibleAnywhere, Category = "Components")
UCameraComponent* Camera;
  • 创建组件:
    T* CreateDefaultSubobject<T>(const FName& SubobjectName);
    T:表示要创建的组件的类型,例如 UStaticMeshComponent、UCapsuleComponent等。
    SubobjectName:传入一个 FName 类型的名称,用于标识该子对象

  • 附加组件:
    将一个子组件附加到父组件
    void SetupAttachment(父组件名称)

CapsuleComp = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule Collider"));
RootComponent = CapsuleComp;

BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Base Mesh"));
BaseMesh->SetupAttachment(CapsuleComp);

TurretMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Turret Mesh"));
TurretMesh->SetupAttachment(BaseMesh);

ProjectileSpawnPoint = CreateDefaultSubobject<USceneComponent>(TEXT("Spawn Point"));
ProjectileSpawnPoint->SetupAttachment(TurretMesh);

前向声明

减少头文件包含个数从而减少编译时间


防止循环


用法:
在.h文件中使用class前向声明
在.cpp文件需要使用时包含需要的头文件


Auto Possess Player

在蓝图中设置:
1.当游戏开始时,指定的玩家控制器会自动附加到角色,使得玩家能够立即控制该角色
2.可以设置为自动控制特定的玩家(如 Player 0、Player 1 等),这对于支持多人游戏非常重要
3.Player 0:自动控制第一个玩家(通常是本地玩家)
Player 1:自动控制第二个玩家(适用于多人游戏)

在C++中设置:

AutoPossessPlayer = EAutoReceiveInput::Player0;

设置输入绑定

函数用于绑定玩家输入到角色的功能上

  • 设置输入轴:
  1. 打开 Unreal Engine 编辑器。
  2. 转到 Edit -> Project Settings。
  3. 在左侧菜单中选择 Input。
  4. 在 Axis Mappings 部分,添加一个新的轴映射,命名为 "MoveForward"。
  5. 为该轴映射添加输入(例如,W/S 键或上/下箭头键),并设置相应的值(例如,W 为 1,S 为 -1)。
  • 绑定输入轴:
void MoveForward(float Value);
void Turn(float Value);
void LookUp(float Value);
void ABird::MoveForward(float Value)
{
	if(Controller&&Value!=0)
	{
		AddMovementInput(GetActorForwardVector(), Value);
	}
}

void ABird::Turn(float Value)
{
	AddControllerYawInput(Value);
}

void ABird::LookUp(float Value)
{
	AddControllerPitchInput(Value);
}


void ABird::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)//设置玩家的输入组件
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
    
    //BindAxis用于绑定持续的输入事件
    //1.轴名称:表示绑定的轴的名称,必须与项目设置中的输入相匹配
    //2.对象:指向当前对象的指针
    //3.回调函数:将输入轴 "MoveForward" 绑定到 ABird 类的 MoveForward 函数
	PlayerInputComponent->BindAxis(FName("MoveForward"), this, &ABird::MoveForward);
    PlayerInputComponent->BindAxis(FName("Turn"), this, &ABird::Turn);
    PlayerInputComponent->BindAxis(FName("LookUp"), this, &ABird::LookUp);
}

  • 在蓝图中添加移动组件:

    可以在FloatingPawnMovement中更改Actor速度
  • 使用控制器旋转:
  • 设置Collision:

弹簧臂附加到相机组件

SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
SpringArm->SetupAttachment(RootComponent);

ViewCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("ViewCamera"));
ViewCamera->SetupAttachment(SpringArm);


GameMode






删除BP_Bird

添加Player Start

迁移角色资产

只能添加到Content文件夹

创建Character

创建C++类的Character:



创建蓝图类的Character:


在C++中添加弹簧臂和相机组件

设置骨骼网络资产:

可以自定义材质颜色:
移动到资产页面,复制资产并改名

实现动态修改

取消蓝图控制 控制器的旋转:

在C++中设置控制器旋转为false:

bUseControllerRotationYaw = false;
bUseControllerRotationPitch = false;
bUseControllerRotationRoll = false;


设置绑定轴:

void ASlashCharacter::MoveForward(float Value)
{
	if (Controller && Value != 0.f)
	{
		const FRotator YawRotation(0, GetControlRotation().Yaw, 0);
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
		AddMovementInput(Direction, Value);
	}
	
}

void ASlashCharacter::MoveLeftAndRight(float Value)
{
	if (Controller && Value != 0.f)
	{
		const FRotator YawRotation(0, GetControlRotation().Yaw, 0);
		const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);
		AddMovementInput(Direction, Value);
	}
}

void ASlashCharacter::Turn(float Value)
{
	AddControllerYawInput(Value);
}

void ASlashCharacter::LookUp(float Value)
{
	AddControllerPitchInput(Value);
}
PlayerInputComponent->BindAxis(FName("MoveForward"), this, &ASlashCharacter::MoveForward);
PlayerInputComponent->BindAxis(FName("MoveLeftAndRight"), this, &ASlashCharacter::MoveLeftAndRight);
PlayerInputComponent->BindAxis(FName("Turn"), this, &ASlashCharacter::Turn);
PlayerInputComponent->BindAxis(FName("LookUp"), this, &ASlashCharacter::LookUp);




设置弹簧臂中的Camera Settings:

在蓝图中设置平滑旋转:

设置旋转速度:

在C++中设置平滑旋转:

设置头发组件

【007 Hair and Eyebrows】
https://www.bilibili.com/video/BV1TT2mYqEXr?vd_source=78f7f9f8d415f8df9a79d831bb4f277c

重构项目文件

重构项目会重置Default_Map地图
可能造成vs没有代码提示
删除Binaries,Intermediate,Saved这3个文件

再次打开项目时会提示重构

刷新vs

解决vs没有代码提示的问题

设置动画蓝图



Loop Animation:循环动画


  • 使用蓝图创建3个变量:
    创建一个character蓝图类:

    通过Try Get Pawn Owner获取Character,通过Character获取MoveMent Component,通过Movement Component设置Ground Speed


  • 使用C++创建3个变量:
    创建一个character C++类:


    创建开始动画函数循环动画蓝图:
virtual void NativeInitializeAnimation() override;
virtual void NativeUpdateAnimation(float DeltaTime) override;
void UMyAnimInstance::NativeInitializeAnimation()
{

}

void UMyAnimInstance::NativeUpdateAnimation(float DeltaTime)
{

}



创建3个变量:

获取GroundSpeed变量:

void UMyAnimInstance::NativeInitializeAnimation()
{
	Super::NativeInitializeAnimation();

	MyCharacter = Cast<AMyCharacter>(TryGetPawnOwner());
	if(MyCharacter)
	{
		MyCharacterMovement = MyCharacter->GetCharacterMovement();
	}
}

void UMyAnimInstance::NativeUpdateAnimation(float DeltaTime)
{
	Super::NativeUpdateAnimation(DeltaTime);

	if(MyCharacterMovement)
	{
		GroundSpeed = UKismetMathLibrary::VSizeXY(MyCharacterMovement->Velocity);
	}
}


更改动画蓝图的父类为C++类:

展示父类中创建的3个变量:


设置State Machine:

在State Machine中设置Idle和Run动作切换:

在Idle中添加Idle动画:

在Run中添加Idle动画:

设置Idle切换到Run的蓝图:

设置Run切换到Idle的蓝图:

动作映射

绑定跳跃动作:

PlayerInputComponent->BindAction(FName("Jump"), IE_Pressed, this, &ACharacter::Jump);//Jump函数调用的只是ACharacter中实际存在的函数

设置跳跃动画

创建IsFalling变量用于判断角色当前状态:

UPROPERTY(BlueprintReadOnly)
bool IsFalling;
if(Movement)
{
	Speed = UKismetMathLibrary::VSizeXY(Movement->Velocity);
	IsFalling = Movement->IsFalling();
}



将Ground Locomotion暂存:


设置Main States:

设置OnGround:

设置Inair:


设置Loop:


设置Land:


设置OnGround到InAir:

设置InAir到Loop:

设置Loop到Land:

设置Land到OnGround:
第一个箭头:

第二个箭头:

设置shift奔跑

在蓝图中设置:




在C++中设置:




在动画蓝图C++中添加WalkSpeed变量,并在Character类中设置获取WalkSpeed函数,将其值赋值给Animation类中的WalkSpeed:


设置动画蓝图:


设置脚部IK



分析:










设置collision

为静态网路添加碰撞:

设置碰撞预设:

设置忽略camera:相机会被石头阻挡


设置忽略Pawn:角色可以穿过石头


启用物理引擎:

设置Overlap Events

在蓝图中设置:
设置物体可以与Pawn重叠:


添加碰撞组件:


设置碰撞体重叠:

在游戏中显示碰撞体:


获取特定对象的重叠事件:



在C++中设置:
创建Sphere类:

UPROPERTY(EditAnywhere)
USphereComponent* Sphere;
AItem::AItem()
{
    Sphere = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));
    Sphere->SetupAttachment(RootComponent);
}


创建重叠事件函数:
寻找委托函数:

DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams//一共有6个参数
( 
FComponentBeginOverlapSignature, //委托类型
UPrimitiveComponent, //委托对象
OnComponentBeginOverlap, //委托名称
UPrimitiveComponent*, OverlappedComponent, 
AActor*, OtherActor, 
UPrimitiveComponent*, OtherComp, 
int32, OtherBodyIndex, 
bool, bFromSweep, 
const FHitResult &, SweepResult
);

将参数复制并删除逗号:

UFUNCTION()
void OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
void AItem::OnSphereOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	FString OtherActorName = OtherActor->GetName();
	if(GEngine)
	{
		GEngine->AddOnScreenDebugMessage(1, 30.f, FColor::Red, OtherActorName);
	}
}
void AItem::BeginPlay()
{
	Super::BeginPlay();

	Sphere->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnSphereOverlap);
}




创建重叠结束函数:

UFUNCTION()
void OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
void AItem::OnSphereEndOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
	FString OtherActorName = OtherActor->GetName();
	if(GEngine)
	{
		GEngine->AddOnScreenDebugMessage(1, 30.f, FColor::Blue, OtherActorName);
	}
}
void AItem::BeginPlay()
{
	Super::BeginPlay();

	Sphere->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnSphereOverlap);

	Sphere->OnComponentEndOverlap.AddDynamic(this, &AItem::OnSphereEndOverlap);
}




进入范围:

离开范围:

将Item的Static Mesh设置为剑:

设置武器类

创建以Item为父类的子类Weapon:


创建Weapon蓝图类:

将父类Item中的Transfomed Sin函数继承并在子类Weapon中使用:

将父类Item中Overlap函数设置为虚函数:

在子类Weapon的protected中重写函数:

使用Super来继承父类函数中的代码:

免费动画资源

免费动画资源

添加更多角色动画

在角色的hand骨骼中添加Socket:

添加资产预设:

添加动作预设:


添加角色:
免费动画资源
下载XBot资产:

在Slash中添加Assets文件夹:

添加Miaxamo文件夹:

将XBox资产添加到文件夹:

在虚幻中添加Miaxmo文件夹:

添加XBot文件夹:

使用Import导入资产:


整理资产名称:


添加动画资产:







设置IK Rig:




设置Retarget Root:


设置XBot的Restarget Chain:












设置Character的IK Rig:

将pelvis设置为Retarget Root:











Leg有问题,需要修改:


删除LeftLeg_0并将LeftLeg中改为ball_l:


设置IK Retargeter:










将剑附加到右手上:
在蓝图中设置:




在C++中设置:


设置按键F拿起武器:








设置拿起武器动画切换:
创建UENUM类:







站立动画:

行走动画:

跑步动画:

整理动画蓝图:

添加动画蓝图:



创建缺少的常量:



添加动画蓝图:






蒙太奇动画

设置武器攻击:
在蓝图中设置:







在C++中设置:
添加蒙太奇动画:

设置攻击键:

使用固定攻击动画2:

随机攻击动画:

将蒙太奇动画封装为函数:



设置两段动画结束标志:



添加EActionState枚举类,用于判断当前是否在执行动作


设置Attack函数:

设置AttackEnd函数:


在蓝图中设置当动画结束时调用AttackEnd函数:



设置蒙太奇动画:

解决武器拿起问题

解决武器拿起跳动问题:
删除蓝图中的节点:

在C++中设置:
创建是否手持武器的枚举类:


如果没有手持武器,则武器上下跳动:

在Weapon中的Equip函数中设置ItemState:

解决在攻击动画期间可以跳跃和移动,以及在跳跃期间可以攻击的问题:
增加跳跃的虚函数:

在移动和跳跃前判断当前状态:

更改跳跃函数:

在跳跃期间不可攻击:

设置声音

添加声音:




使用UE4旧内容设置:





使用UE5新内容设置:

设置MetaSound:



设置随机音量和声调:

  • 添加角色喘气音效:


设置随机音效:将多种声音作为数组传递



  • 添加角色跑步音效:



开启Enable Shared State:将声音用于共享的动作中从而共享声音

在固定跑步动画中设置,而不是蒙太奇动画中设置:

  • 添加重物晃动的声音:



  • 添加跑步时衣服声音:



  • 添加跳跃声音:





添加落地声音:

添加起跳声音:

  • 添加拿取Weapon时的声音:

添加PouchHeavy声音:

添加Shink声音:


只在装备的一瞬间发出声音:


为Equip Sound添加资产:

  • 添加Niagara跑步时的特效:


设置特效产生的位置:

装备武器和卸下武器

添加蒙太奇动画:











添加Arm和Disarm事件:

重构函数:




  • 设置奔跑跳跃时不能切换武器:

添加EquippingWeapon状态


修改ActionState:

跳跃时禁止切换:

添加动作结束标志:

添加结束函数,将ActionState重新设置为Unoccupied:


将结束标志链接到结束函数上:

修复武器挥动时可以按F发出声音的问题

拿起武器时,Overlapping Item是None
挥动武器时,由于武器碰撞体与Character相撞,导致Overlapping Item变为BP_Weapon

将碰撞球体放到protected类中:


若装备了武器,则将碰撞球体设置为无碰撞:

编辑动画

013 Editing Animations
1.先确定好开始和最后的动画位置,并将需要修改的每个骨骼点击Key键
2.在动画中间部分调整需要调整的骨骼,直接按Key键(不需要每个都按一下)

作为新动画导出:

设置Weapon碰撞体




设置测试碰撞球体:

勾选墙体的Generate Overlap Events:

设置Tracing


在蓝图中设置:
添加两个Scene:



添加Trace:



设置武器攻击角色时也能显示效果:
将WeaponBox的Pawn设置为Ignore:


添加一个角色实例并设置实例:


在C++中设置:






设置只在攻击动画时使用Tracing

在动画蓝图中添加EnableCollison和DisableCollison并在蓝图面板中使用:

先将开始时的WeaponBox中的CollisonEnable设置为NoCollision:

获取私有变量WeaponBox:

在SlashCharacter中添加SetWeaponCollision函数并暴露到蓝图面板中使用:


在蓝图面板中设置EnableCollision:

添加Enemy

添加Enemy的C++类:


添加Enemy蓝图类:


设置Blender

设置Blender以转换没有root的角色
009 Root Motion Animations
Mixamo 转换器

添加接口








设置被攻击montage动画

创建并设置蒙太奇动画:


创建动画蓝图:






启用EnableRootMotion,从而使Enemy被攻击时按root移动:


设置被攻击移动方向:




  • 设置一次攻击只会移动一次:

在public中创建一个IgnoreActors数组,每次重叠时将重叠物体放入IgnoreActors数组,然后重叠结束时清除IgnoreActors数组:


在DiableCollision中清除IgnoreActors:


添加被攻击音效



重构函数:



在ImpackPoint位置Play Sound:


设置音效衰减





测试函数:

设置血液特效




设置剑残影特效

添加剑头和剑尾的插件:




在montage动画中添加Trail:



按V切换第一人称

视频

按E查看Node

视频

设置按键可视化交互

视频

添加可破碎的罐子





将0破碎,使每个碎片破碎为更小的碎片:

设置场地系统用于破坏罐子




先添加外部压力破碎罐子,然后添加线性压力使碎片飞走:

设置武器攻击破坏罐子

在C++中设置蓝图函数:


设置蓝图函数:


设置Destructible的Collision Type:

创建罐子类


创建C++类:


设置Module:




创建蓝图类:



设置Blueprint Native Event




在BreakableActor中重写GetHit:



设置击碎罐子声音



设置罐子破碎后消失


免费声音资源

网站

添加宝藏

添加拾取声音:



添加宝藏类:
创建Item的子类:


重写虚函数:


创建BP蓝图类:


设置宝藏的Mesh和Sound:

设置破坏罐子spawn宝藏


在蓝图中设置:


在C++中设置:
设置TSubclassOf:指定蓝图中特定的类





设置出现随机宝藏




添加更多可破坏的罐子

先添加Geometry Collection:


将Collision设置为Box:

创建子类BP类并重新设置Mesh和Capsule大小:


设置宝藏种类:

设置无宝藏罐子

复制BP罐子而不是创建子类:

将宝藏种类设置为空:

创建Niagara





设置Niagara:







在C++中创建Niagara组件:
先在Slash.Build.cs中添加Niagara并在关闭虚幻然后在vs中启动虚幻:



在Treasure中设置Niagara组件:

在Weapon中设置Niagara组件:

在C++中设置equip时停用Niagara组件:

添加Health组件

创建Health组件:



将组件附加到Enemy上:


结果:

创建Health的Widget







创建添加Widget的C++类:








创建HealthBarComponent的C++父类HealthBar





将父类设置为WealthBar:

在HealthBarComponent中添加设置健康百分比函数:


将Enemy中原先的UWidgetComponent改为UHealthBarComponent:

设置Damage使Health减少



在AActor类中查找TakeDamage函数:


将TakeDamage函数添加到Enemy中:


在Equip函数中添加参数并重新设置所有Equip函数:



添加ApplyDamage函数:

添加ReceiveDamage和GetHealthPercent函数:


设置TakeDamage函数:

设置自定义Widget样式









posted @ 2024-09-17 16:26  pone1  阅读(15)  评论(0编辑  收藏  举报
音乐