[UE4入门笔记(8)] 23.UE4资源加载 24.UE4物体碰撞设置 25.添加模型与摄像机 26.添加动作蓝图 27.角色移动 --梁迪老师UE4纯C++&Slate开发沙盒游戏

前言:

笔者目前在校本科大三,目标方向是人工智能、计算机视觉。上一个OpenCV学习笔记专栏已完结,在学习完OpenCV后,我继续学习C++,并用纯C++做UE4项目的方式继续提升自己的水平。

梁迪老师的水平非常高,他的课程本来也无需笔记:课程本身即为最好的笔记。但由于我天赋有限,还是边看边记,以防遗忘——知识点太多,步骤太繁杂了。在学习过程中,我也偶有思考,思索为什么某个方法老师要这样做。所以,一是为了记录,二是为了分享,才有了这个专栏。

内容方面,由于我在开启这个专栏时,此项目已经做完很多了。所以,前期的一些大篇幅叙述的知识,可能在后期应用中一带而过。以及,前期的一些知识,后期会重新剖析,并加上我的个人理解。

另外,若有学术交流/学业交流意愿,可以邮件联系1246210283@qq.com,希望一齐进步。


本篇学习内容:

23.UE4资源加载
24.UE4物体碰撞设置
25.添加模型与摄像机
26.添加动作蓝图
27.角色移动


23.UE4资源加载

Uobject资源加载:
ConstructorHelpers::FObjectFinder<T> 只能在构造函数使用
LoadObject<T> 可以在任何地方使用

蓝图资源加载:
ConstructorHelpers::FClassFinder<T> 只能在构造函数使用
LoadClass<T> 可以在任何地方加载

注:蓝图加载路径最后一定要加_C

使用案例:
例如,我们需要给新建的PlayerCharacter的默认Mesh添加资源
在其构造函数中,写如下代码即可:

static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(TEXT("SkeletalMesh'/Game/Res/PolygonAdventure/Mannequin/Player/SkMesh/Player.Player'"));
GetMesh()->SetSkeletalMesh(StaticMeshThird.Object); //获取默认的Mesh:GetMesh()

24.UE4物体碰撞设置

如果要进行物理碰撞,那么需要勾选Physics下的Simulate Physics Collision下的Simulation Generates Hit Events,并且需要设置Collision Enabled,随后要把可以碰撞的其他物体的碰撞选为Block。
如果要进行物体交互检测,那么只选Collision下的Generate Overlap Events即可,随后设置其他物体的碰撞选为Overlap。
如果其他物体的碰撞设为Ignore,则会忽略碰撞检测和交互事件。

这些属性可以用代码设置,也可以在Project Settings下Collision下Preset先建立一个属性表,然后在写代码时直接应用此属性表即可。

25.添加模型与摄像机

(1)创建一个PlayerCharacter,除了类本身自带的函数以外,需要添加以下变量:

private:
	//第一人称的骨骼模型
		//VisibleDefaultsOnly:要在C++里写好,在蓝图里不能修改
		//如果第一个参数是EditAnywhere,那么要放在public或者protected下面
	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		USkeletalMeshComponent* MeshFirst;
public:
	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		class USpringArmComponent* CameraBoom; //相当于一个摄像机的摇杆
	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		class UCameraComponent* ThirdCamera;
	UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
		UCameraComponent* FirstCamera;

(2)随后围绕构造函数来写:(这里全部列出主要是记下相关API)

//添加第一人称骨骼模型
static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshFirst(
	TEXT("SkeletalMesh'/Game/Res/PolygonAdventure/Mannequin/FirstPlayer/SkMesh/FirstPlayer.FirstPlayer'"));
MeshFirst = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("MeshFirst"));
MeshFirst->SetSkeletalMesh(StaticMeshFirst.Object);
MeshFirst->SetupAttachment((USceneComponent*)GetCapsuleComponent());//把这个组件添加到GetCapsuleComponent()的子集
MeshFirst->bOnlyOwnerSee = true;
MeshFirst->bCastDynamicShadow = false; //不渲染第一人称的影子
MeshFirst->bReceivesDecals = false;
// *更新频率衰落
MeshFirst->MeshComponentUpdateFlag = EMeshComponentUpdateFlag::OnlyTickPoseWhenRendered;
MeshFirst->PrimaryComponentTick.TickGroup = TG_PrePhysics;
//设置碰撞属性
MeshFirst->SetCollisionObjectType(ECC_Pawn);
MeshFirst->SetCollisionEnabled(ECollisionEnabled::NoCollision);
MeshFirst->SetCollisionResponseToAllChannels(ECR_Ignore);
//设置位移
MeshFirst->SetRelativeLocation(FVector(0.f, 0.f, -95.f));
MeshFirst->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f)));


//给默认Mesh添加骨骼模型
static ConstructorHelpers::FObjectFinder<USkeletalMesh> StaticMeshThird(
	TEXT("SkeletalMesh'/Game/Res/PolygonAdventure/Mannequin/Player/SkMesh/Player.Player'"));
//USkeletalMesh* h = StaticMeshThird.Object;
GetMesh()->SetSkeletalMesh(StaticMeshThird.Object); //获取默认的Mesh:GetMesh()

GetMesh()->bOnlyOwnerSee = true;//只有本人能看见这个模型
GetMesh()->bReceivesDecals = false;//是否允许影子等反射到其上 可以节省资源
GetMesh()->SetCollisionObjectType(ECC_Pawn);//设置碰撞类型:Pawn类型
GetMesh()->SetCollisionEnabled(ECollisionEnabled::NoCollision);//设置不允许碰撞
GetMesh()->SetCollisionResponseToAllChannels(ECR_Ignore);//设置这个物体对所有其他物体的碰撞都是忽略的
GetMesh()->SetRelativeLocation(FVector(0.f, 0.f, -95.f));//设置位置
GetMesh()->SetRelativeRotation(FQuat::MakeFromEuler(FVector(0.f, 0.f, -90.f)));//设置旋转:从欧拉角转换为四元数


//摄像机手臂
CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
CameraBoom->SetupAttachment(RootComponent);
//设置距离
CameraBoom->TargetArmLength = 300.f;
//设置偏移
CameraBoom->TargetOffset = FVector(0.f, 0.f, 60.f);//向上偏移60
//绑定controller的旋转
CameraBoom->bUsePawnControlRotation = true; //绑定的是playercontroller的旋转

//初始化第三人称摄像机
ThirdCamera = CreateAbstractDefaultSubobject<UCameraComponent>(TEXT("ThirdCamera"));
ThirdCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); //获取SocketName并绑定
//设置第三人称摄像机不跟随控制器的旋转
ThirdCamera->bUsePawnControlRotation = false;

//初始化第一人称摄像机
FirstCamera = CreateAbstractDefaultSubobject<UCameraComponent>(TEXT("FirstCamera"));
FirstCamera->SetupAttachment((USceneComponent*)GetCapsuleComponent());
//设置跟随controller旋转
FirstCamera->bUsePawnControlRotation = true;
//设置位置
FirstCamera->AddLocalOffset(FVector(0.f, 0.f, 60.f)); //在头部

注:其中的 CreateDefaultSubobject是UE4创建组件的方法,SetupAttachment是添加该组件到何组件下。组件与组件的包含关系及添加模型后的效果,可以在UE4编辑器中创建一个基于此类的蓝图类,然后打开蓝图类进行查看。

26.添加动作蓝图

(1)创建动画 - 动画蓝图,并选择继承自创建好的动画类,以及选择对应的骨骼资源。
(2)在动画类里提前创建好Speed、Direction、IsInAir等元素,这样在蓝图类里就可以识别到。
(3)在创建好的动画蓝图类中添加一个状态机,在状态机里实现动作之间的切换和循环。

27.角色移动

(1)首先需要到Project Settings下的Input的Axis Mappings下添加一个新元素MoveForward,并在其下添加W/S/Up/Down四个键来进行前后移动。注意Action Mappings是按键之后进行一个动作,而Axis Mappings是要传值的,所以我们将S和Down的值改为-1.0。

(2)随后添加各个元素。

(3)随后在PlayerCharacter的SetupPlayerInputComponent函数中进行设置。

PlayerInputComponent->BindAxis("MoveForward", this, &ASlAiPlayerCharacter::MoveForward);

注:实际上在Controller下也可以进行绑定,区别如下:在Character下绑定的是移动方面的动作,在Controller下绑定打开UI等动作。

(4)实现传入的函数指针对应的函数,如:

void ASlAiPlayerCharacter::MoveForward(float Value)
{
	if (Value != 0.f && Controller)
	{
		const FRotator Rotation = Controller->GetControlRotation(); //获取了controller的旋转
		FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X); //把controller旋转的X方向拿到Direction中
		AddMovementInput(Direction, Value); //在这个方向上添加Value大小的位移
	}
}

(5)这样设置完之后,人物移动时是没有动画的,所以还需要添加动画。创建一个动画蓝图,并设置好状态机的逻辑,然后需要在Character的构造函数中把蓝图动作资源读取到骨骼模型上。
此外,角色的初始速度、方向、是否在空中等参数也需要设置。

然后,在PlayerAnim中创建一个指向Character的指针,完成初始化函数、更新参数函数,并将其添加到帧更新函数中,注意:这样是为了避免子类要重写父类的帧更新函数,这样子类只需要重写更新参数函数即可。

void USlAiPlayerAnim::NativeUpdateAnimation(float DeltaSeconds)
{
	//初始化角色指针
	InitSPCharacter();
	//更新蓝图数据
	UpdateParameter();
	
}

void USlAiPlayerAnim::InitSPCharacter()
{
	if (!SPCharacter) SPCharacter = Cast<ASlAiPlayerCharacter>(TryGetPawnOwner());
}

void USlAiPlayerAnim::UpdateParameter()
{
	//如果不存在直接返回,避免空指针产生中断
	if (!SPCharacter) return;
	//设置速度
	Speed = SPCharacter->GetVelocity().Size();//获取速度向量的模
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值