当前位置:   article > 正文

UE5 C++ 斯坦福 Note1_setdefaultsubobjectclass

setdefaultsubobjectclass

Class Hierarchy (类的层次结构)

  • Object 所有虚幻实例(UObject)的基类
  • √ Actor 可以被放置或生成在世界中的Object
  • √ √ Pawn 可以被玩家或AI控制的Actor
  • √ √ √ Character 包含步行移动组件的Pawn
  • √ √ √ √ *Character 我们继承重写的C++类

Class Prefixes (类的前缀)

虚幻引擎需要类始终保持前缀

  • U - 派生自UObject的类
  • A - 派生自Actor的类
  • F - 结构体
  • E - 枚举
  • I - 接口

BeginPlay

在Character刚被加载的时候首先调用
如果它被执行,那么它已经被完全加载,完全初始化,这是我们可以信赖的第一件事。

Tick

每一帧都会被调用,也传递了一个delta时间访问

相机组件

UCameraComponent

弹簧臂组件

USpringArmComponent

创建实例

CreateDefaultSubobject<CLASSNAME>(“TABNAME”)
其中CLASSNAME是实例的类型,TABNAME是它在编辑器中显示的名字

数据视图与完整蓝图编辑器

数据视图很难读懂正在发生的事情
蓝图读起来比较快

C++层暴露组件,适当的显示出细节面板

设置弹簧臂正确的附着

弹簧臂 SetupAttachment(RootComponent)

RootComponent是层次结构中的第一个组件

设置相机正确的附着

相机 SetupAttachment(弹簧臂)

相机安装在弹簧臂上

因为我们想要角色和相机之间有一定的距离

Unreal Property System (虚幻资产系统)

UPROPERTY,UFUNCTION,UCLASS,USTRUCT,UENUM(Unreal Macros 虚幻宏)

标记C++类,用于像编辑这样的事情,蓝图访问,甚至对于网络行为。

定义你的代码应该在哪里运行,服务器还是在本地客户机上。

而且也是为了内存管理,将会用于追踪指针和一个对象的内存,

比如

UProperty(VisibleAnywhere) //它将在任何地方可见
  • 1

玩家输入组件

void AMainCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);
	// 加两个输入事件控制相机
	// 轴运算
	PlayerInputComponent -> BindAxis("LookRight", this,&AMainCharacter::AddControllerYawInput);
	PlayerInputComponent -> BindAxis("LookForward", this,&AMainCharacter::AddControllerPitchInput);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我们其实有两个选择,BindAction和BindAxis
在目前我们对绑定轴感兴趣,因为希望能够移动前进和倒退。

我们可以联想一下,输入设备是GamePad的情况,拇指杆滑动,会在-1到1的区间里变化。

在输入设备是键盘的情况下,它仅仅是按下Key和松开Key的问题(0,1 二值)。

BindAxis 参数 (名称,接收输入对象,想要触发的函数)
触发委托之后,会把名称传递给接收输入对象,传递一个需要被触发的函数

移动函数

Character已经封装了一些函数,
我们只需要说出往哪个方向走

目前只需要前后左右四个方向,就可以用函数直接获取。
再传递一个value 是一个-1到1的值

AddMovementInput(GetActorForwardVector(),value);
  • 1

绑定一个键

打开编辑器的项目设置,输入,绑定

旋转函数

直接使用Pawn中提供的函数即可

APawn::AddControllerYawInput

在VS2019 IDE中 可以直接Ctrl+鼠标左键,跳转到对应函数,查看源码。

虚幻引擎的一个问题是,它有800万行的代码,检索代码是很慢的

此处包含pitch、yaw、roll等知识点

Yaw 指的是水平旋转,pitch 指的是垂直旋转,roll 未知

PlayerCharacter蓝图编辑

打开PlayerCharacter蓝图
左上角会有
CapsuleComponent
ArrowComponent
Mesh
SpringArmComp (前面写的C++基类里的)
CameraComp (前面写的C++基类里的)
CharacterMovement

选中Mesh进行模型更换

从detail页签可以随意修改模型引用路径

可以在Transform里修改位置和朝向

在Animation 选择Anim Class 动画蓝图或者动画C++基类

动画的意义:看一下自己角色的状态(比如:移动速度有多快,哪个方向,是不是在做攻击之类的事情)并且融合各种姿势和动画,合成一个最终的姿势。

Idle Pos 闲置状态。

版本管理

git里面 可以看到修改了哪些文件,改动了哪些行

.uproject 文件

.uproject 文件 其实就是很像Json格式的明文字符串。

下面是我打开了自己的一个项目的.uproject文件

{
	"FileVersion": 3,
	"EngineAssociation": "{*******-****-****-****-*******}",
	"Category": "",
	"Description": "",
	"Modules": [
		{
			"Name": "UE5Build",
			"Type": "Runtime",
			"LoadingPhase": "Default",
			"AdditionalDependencies": [
				"Engine"
			]
		}
	],
	"Plugins": [
		{
			"Name": "ModelingToolsEditorMode",
			"Enabled": true,
			"TargetAllowList": [
				"Editor"
			]
		}
	]
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

Config/DefaultInput.ini

很多外部生成的内容,和我们自己绑定的输入。

UEC++项目的 Git提交目录

/Config/
/Content/
/Source/
/.gitignore
/**.uproject
/README.md

.sln文件 会被.uproject编译的时候生成。

GIT分析语言组成:C# 66.6% C++ 28.5% C 4.9%
C#主要是UBT和UHT自动生成的配置文件,占用较大。
C++是UObject类逻辑的主要实现地方,比C大一些。
C是UObject类的声明,不负责实现,占用最小。

碰撞与物理学

每个Player都有一个PlayerController

一旦他加入游戏,就会被分配到一个框架
而且他会持有这个PlayerController直到他离开游戏或者地图被加载。

这里PlayerController可能会控制一个Pawn,这个Pawn会死,也会重生,也会看到其他人死掉的Pawn。

AI也是使用相似的类,AIController从Controller中驱动。

通过控制器方向调整人物朝向

在PlayerCharacter蓝图中,勾选Pawn页签中的Use Controller Rotation

把这个勾选去掉的话,移动鼠标旋转相机的同时,人物朝向不会再随着相机(实际上是关联的控制器)旋转了。

再打开PlayerCharacter蓝图中的SpringComp,勾选CameraSettings页签中的Use Pawn Control Rotation

把这个勾选去掉的话,移动鼠标旋转的同时,相机不会再随着关联的控制器旋转了。

这里的做法是为了可以让角色有机会看向相机,比如Dark Soul和Final Fantasy的运动机制。

CharacterMovement的参数是十分庞大的,我们现在想把旋转定位到运动上,用最上方的快速搜索栏,搜索orient,找到Orient Rotation To Movement(定向旋转)

这是一个小技巧,想要找CharaterMovement中是否存在这样的变量,就在蓝图中搜索吧,之后再去C++代码里编写修改这个值的地方。

编码规范,bool类型的变量前面要加b字母

GetCharacterMovement()->bOrientRotationToMovement = True;
  • 1

这将使我们的Character旋转,我们目前正朝着什么方向移动。

而不是只能向正面直直的移动,我们有侧面的移动。

这时候Character的CPP报错了,因为我们在调用CharacterMovement类的函数,却没有对CharacterMovement的声明。

#include "GameFramework/CharacterMovementComponent.h"
  • 1

目前的效果是按下D会原地旋转,按下W会直直的向前走。

对于前进的步伐,我们实际上想要的不是Pawn当前的方向,而是要向摄像机的方向移动。

UE5默认的镜头方式其实是射击类游戏喜欢用的视角。

现在我们要做的是类似黑魂、只狼、最终幻想之类的游戏。

我们现在可以得到Controller的旋转,

FRotator ControlRot = GetControlRotation();
  • 1

AddMovementInput函数期望的是一个矢量,而不是一个旋转器(Rotator),但是我们可以非常容易地来回转换,在向量和Rotator之间转换,

AddMovementInput(ControlRot.Vector(),value);
  • 1

因为我们只对yaw感兴趣,yaw是水平旋转,我们不关心俯仰(pitch roll)的问题,

ControlRot.Pitch = 0.0f;
ControlRot.Roll = 0.0f;
  • 1
  • 2

左右旋转不正常
Find Symbol工具
搜索rightVector,查询所有带这个词的函数

搜到 UKismetMathLibrary.GetRightVector

很多时候我们知道一个函数在蓝图里叫什么,但是不知道它在C++里叫什么,一些BOOL值可以通过命名规范推算出来,
Kismet的意思是蓝图(BluePrint) 在UE3中的老人都是这么说的,当提到Kismet在引擎代码或者其他地方,它意味着蓝图数学库。

  • Character局部坐标系的XYZ
    X轴正方向是角色面朝的正前方 (Red红色)
    Y轴正方向是角色的右方向 (Green绿色)
    Z轴正方向是角色的头顶 (Blue蓝色)
FVector RightVector = FRotationMatrix(ControlRot).GetScaledAxis(EAxis::Y);
  • 1

EAxis::Y 就是枚举类型命名空间的常量Y的值

Play期间不显示鼠标

Play的右边下拉菜单,找到高级设置,Play in Editor页签的第一个Game Gets Mouse Control

快速热更新

Editor preference -> General -> Loading & Saving
Startup页签下有加载级别的设置,设置为last opened

魔法投射物

USphereComponent 是碰撞组件,这是最基本的
UProjectileMovementComponent 投射物运动组件,给定一个速度,它就会直直的移动
UParticleSystemComponent 粒子系统组件,让我们有东西可以展示出来

附加层级

EffectComp->SetupAttachment(SphereComp);
  • 1

新建蓝图类

选择父类,魔法投射物C++类

在世界中创建一个actor

需要传递创建实例的类型,transform参数(是一个结构体,在比例尺中保存一个位置和旋转),生成参数结构体。

GetWorld()->SpawnActor<AActor>(ProjectileClass, SpawnTM, SpawnParams);
  • 1

构造transform结构体

FTransform SpawnTM = FTransform(GetControlRotation(), GetActorLocation());
  • 1

构造生成所需参数结构体

FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = FSpawnActorCollisionHandlingMethod::AlwaysSpawn;
  • 1
  • 2

生成碰撞的覆盖处理,当物体在世界上产生的时候,将会检查它的碰撞,可以移动一些位置,让出现的时候不要和任何东西重叠。

声明一个可编辑的类型

UPROPERTY(EditAnyWhere)
TSubClassOf<AActor> ProjectileClass;
  • 1
  • 2

EditAnyWhere:在编辑器中可编辑
VisibleAnyWhere:在编辑器中可看

打开PlayerCharacter蓝图就能看到了,直接在里面编辑。

获取骨骼插槽位置

FVector HandLocation = GetMesh()->GetSocketLocation("Muzzle_01"); // 骨骼名
// 通过新的位置产生Transform结构体
FTransform SpawnTM = FTransform(GetControlRotation(), HandLocation);
  • 1
  • 2
  • 3

UE4的骨骼树中,灰色的名字是Socket插槽,白色的名字是普通的骨头。

设置魔法投射物不下落

重力设置为0

打开魔法投射物蓝图,选中MovementComp
打开细节面板 找到Projectile页签下的 Projectile Gravity Scale 改为0

控制魔法投射物的物理

打开魔法投射物蓝图,选中球体组件
打开细节面板 找到Collision页签

Visible :AI能否看到你
Camera: 相机能否穿过组件

碰撞条件会发生在两个物体相互之间最小的层级。
比如你认为可以碰撞对方,但是对方认为不能碰撞你,那么就不会碰撞上。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/735684
推荐阅读
相关标签
  

闽ICP备14008679号