3、 两个引擎的部分术语对比:
4.7、From GameObjects to Actors 从GameObjects到Actors
GameObject在UE4中如何体现?UE4有一个 Gameplay Framework 系统来使用这些Actors工作。
5.1、UE4中,系统也将提供给我们两个函数,他们分别是 InitializeComponent() 函数和 TickComponent()函数,这两个函数和Unity中Start()函数和Update()函数类似
5.2、Scriptable Actor Blueprint Classes 可以编辑的Actor蓝图类
5.2.1、你新建的 Actor蓝图类(此处不是组件蓝图类)可以使用蓝图来实现可视化编辑。
5.2.2、代码实现功能的C++类。下面给出了三个的对应关系。
5.2.2、UE4 C++
#pragma once
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
int Count;
// Sets default values for this actor's properties.
AMyActor()
{
// Allows Tick() to be called
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned.
void BeginPlay()
{
Super::BeginPlay();
Count = 0;
}
// Called every frame.
void Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
Count = Count + 1;
GLog->Log(FString::FromInt(Count));
}};
5.6、Transform Components Transform组件
Actors有一个叫做RootComponent的组件,Actor在世界中拥有位置、旋转、缩放属性,
6.3、Writing Event Functions (Start, Update, etc.) 写事件函数
6.3.2、C++ :
UCLASS()
class AMyActor : public AActor{
GENERATED_BODY()
// Called at start of game.
void BeginPlay();
// Called when destroyed.
void EndPlay(const EEndPlayReason::Type EndPlayReason);
// Called every frame to update this actor.
void Tick(float DeltaSeconds);};
6.3.4、UE4中的组件包含一些不同的函数,下面列举了一些简单例子:
C++ :
UCLASS()
class UMyComponent : public UActorComponent{
GENERATED_BODY()
// Called after the owning Actor was created
void InitializeComponent();
// Called when the component or the owning Actor is being destroyed
void UninitializeComponent();
// Component version of Tick
void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);};
请记住,在UE4中,调用父类的函数的版本是非常重要的。
比如说,在unity里面这样写:base.Update();而在UE4中则需要这样写:Super::TickComponent();
void UMyComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
// Custom tick stuff here
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}
UE4的C++代码中,字母前缀'A'表示是Actor的子类,'U'表示Object的子类。当然还有一些其他的前缀,比如‘F’,表示是一些空白的数据结构或者不是Object类。
6.3.6、Writing gameplay code in UE4 在UE4中编写游戏代码
6.3.6.1、Instantiating GameObject / Spawning Actor 实例化一个物体
NewObject()函数是用来创建UObject类型的物体,SpawnActor()函数是用来创建AActor类型的物体。
UE4中,这样写:
- UMyObject*NewObj=NewObject<UMyObject>();
那对于Actor类型的物体如何实例化呢?Actors物体是通过使用一个UWorld类型的World物体上的SpawnActor()函数来实例化的。一些UObject提供了GetWorld()函数,比如所有的Actors类就可以给你提供这个函数。观察下面的函数,我们发现,我们需要传递进来的第一个参数是我们想要实例化的Actor的类,而不是Actor本身。在我们的实例中,这个类可以使AMyEnemy的任何子类。
但是如果我想复制一个物体,我该使用哪一种盛丽华的函数呢?NewObject()函数和SpawnActor()函数都个可以提供一个“template(模板)”物体来使用。虚幻引擎将会从这个物体来复制,而不是从头开始实例化对象,这样做将会把他的所有的UPROPERTYs(属性特性)和组件拷贝到。
·
AMyActor* CreateCloneOfMyActor(AMyActor* ExistingActor,
FVector SpawnLocation,
FRotator SpawnRotation)
{
UWorld* World = ExistingActor->GetWorld();
FActorSpawnParameters SpawnParams;
SpawnParams.Template = ExistingActor;
World->SpawnActor<AMyActor>(ExistingActor->GetClass(), SpawnLocation, SpawnRotation, SpawnParams);
}
在UE中,使用物体的构造函数来实现相同的功能。
UCLASS()
class AMyActor : public AActor{
GENERATED_BODY()
UPROPERTY()
int32 MyIntProp;
UPROPERTY()
USphereComponent* MyCollisionComp;
AMyActor() {
MyIntProp = 42;
MyCollisionComp = CreateDefaultSubobject<USphereComponent>(FName(TEXT("CollisionComponent"));
MyCollisionComp->RelativeLocation = FVector::ZeroVector;
MyCollisionComp->SphereRadius = 20.0f;
}};
在AMyActor的构造函数中,我们给这个类设置了默认的参数值,要记住使用CreateDefaultSubobject()函数。我们可以使用这个函数来创建组件并且为其制定默认的参数。我们使用这个函数创建的所有子物体实际上就是一个默认的模板,因此我们可以在一个子类中或者蓝图中修改他们。
Casting from one Type to Another 类型转换
就是根据已有的组件转换成另一种类型来有条件的处理一些事情。
Collider collider = gameObject.GetComponent<Collider>;
SphereCollider sphereCollider = collider as SphereCollider;
if (sphereCollider != null)
{
// ...
}
UE4 C++:
UPrimitiveComponent* Primitive = MyActor->GetComponentByClass(UPrimitiveComponent::StaticClass());
USphereComponent* SphereCollider = Cast<USphereComponent>(Primitive);
if (SphereCollider != nullptr)
{
// ...
}
6.3.6.1.2、Destroying GameObject / Actor 销毁物体
Disabling GameObjects / Actors 使物体处于不激活状态
6.3.6.1.3、Accessing the GameObject / Actor from Component 通过组件访问物体
Accessing a Component from the GameObject / Actor 通过物体访问组件
C++:
UMyComponent*MyComp=Cast<UMyComponent>(
MyActor->GetComponentByClass(UMyComponent::StaticClass())
);
6.3.6.1.4、Finding GameObjects / Actors 查找物体
// Find GameObject by name
GameObject MyGO = GameObject.Find("MyNamedGameObject");
// Find Objects by type
MyComponent[] Components = Object.FindObjectsOfType(typeof(MyComponent)) as MyComponent[];
foreach (MyComponent Component in Components)
{
// ...
}
// Find GameObjects by tag
GameObject[] GameObjects = GameObject.FindGameObjectsWithTag("MyTag");
foreach (GameObject GO in GameObjects)
{
// ...
}
// Find Actor by name (also works on UObjects)
AActor* MyActor = FindObject<AActor>(nullptr, TEXT("MyNamedActor"));
// Find Actors by type (needs a UWorld object)
for (TActorIterator<AMyActor> It(GetWorld()); It; ++It)
{
AMyActor* MyActor = *It;
// ...
}
// Find UObjects by type
for (TObjectIterator<UMyObject> It; It; ++it)
{
UMyObject* MyObject = *It;
// ...
}
// Find Actors by tag (also works on ActorComponents, use TObjectIterator instead)
for (TActorIterator<AActor> It(GetWorld()); It; ++It)
{
AActor* Actor = *It;
if (Actor->ActorHasTag(FName(TEXT("Mytag"))))
{
// ...
}
}
// Checks if an ActorComponent has this tag
if (MyComponent->ComponentHasTag(FName(TEXT("MyTag"))))
{
// ...
}
6.3.6.1.8、Physics: RigidBody vs. Primitive Component 物理部分:RigidBody 对比 Primitive 组件
虚幻引擎把可能的物理和可视化组合在PrimitiveComponent组件中。任何一个组件都在世界中拥有集合属性,他们可以被渲染出来也可以和拥有PrimitiveComponent组件的物体相互作用。
6.3.6.1.9、Layers vs Channels Unity中的Layers和UE4中的Channels
6.3.6.1.10、RayCast vs RayTrace 光线投射
6.3.6.1.10.2、C++
APawn* AMyPlayerController::FindPawnCameraIsLookingAt()
{
// You can use this to customize various properties about the trace FCollisionQueryParams Params;
// Ignore the player's pawn
Params.AddIgnoredActor(GetPawn());
// The hit result gets populated by the line trace
FHitResult Hit;
// Raycast out from the camera, only collide with pawns (they are on the ECC_Pawn collision channel)
FVector Start = PlayerCameraManager->GetCameraLocation();
FVector End = Start + (PlayerCameraManager->GetCameraRotation().Vector() * 1000.0f); bool bHit = GetWorld()->LineTraceSingle(Hit, Start, End, ECC_Pawn, Params);
if (bHit)
{
// Hit.Actor contains a weak pointer to the Actor that the trace hit
return Cast<APawn>(Hit.Actor.Get());
}
return nullptr;
}
6.3.6.1.11、Triggers 触发器
6.3.6.1.11.2、UE4 C++:
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
// My trigger component
UPROPERTY()
UPrimitiveComponent* Trigger;
AMyActor()
{
Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("TriggerCollider"));
// Both colliders need to have this set to true for events to fire Trigger.bGenerateOverlapEvents = true;
// Set the collision mode for the collider
// This mode will only enable the collider for raycasts, sweeps, and overlaps Trigger.SetCollisionEnabled(ECollisionEnabled::QueryOnly);
}
void BeginPlay()
{
// Register to find out when an overlap occurs OnActorBeginOverlap.AddDynamic(this, &AMyActor::OnTriggerEnter); OnActorEndOverlap.AddDynamic(this, &AMyActor::OnTriggerExit);
Super::BeginPlay();
}
void EndPlay(const EEndPlayReason::Type EndPlayReason)
{
OnActorBeginOverlap.RemoveDynamic(this, &AMyActor::OnTriggerEnter); OnActorEndOverlap.RemoveDynamic(this, &AMyActor::OnTriggerExit); Super:EndPlay(EndPlayReason);
}
UFUNCTION()
void OnTriggerEnter(AActor* Other);
UFUNCTION()
void OnTriggerExit(AActor* Other);
};
6.3.6.1.12、Kinematic Rigidbodies 运动学
在UE4中,碰撞组件和刚体组件是一个东西。他们的父类是UPrimitiveComponent,他又很多子类来满足你的需求,比如USphereComponent,UCapsuleComponent等等。
6.3.6.1.12.2、UE4 C++:
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
UPrimitiveComponent* PhysicalComp;
AMyActor()
{
PhysicalComp = CreateDefaultSubobject<USphereComponent>(TEXT("CollisionAndPhysics")); PhysicalComp->SetSimulatePhysics(false);
PhysicalComp->SetPhysicsLinearVelocity(GetActorRotation().Vector() * 100.0f);
}
};
6.3.6.1.13、Input events 输入事件
6.3.6.1.13.2、UE4 C++
UCLASS()
class AMyPlayerController : public APlayerController
{
GENERATED_BODY()
void SetupInputComponent()
{
Super::SetupInputComponent();
InputComponent->BindAction("Fire", IE_Pressed, this, &AMyPlayerController::HandleFireInputEvent);
InputComponent->BindAxis("Horizontal", this, &AMyPlayerController::HandleHorizontalAxisInputEvent);
InputComponent->BindAxis("Vertical", this, &AMyPlayerController::HandleVerticalAxisInputEvent);
}
void HandleFireInputEvent();
void HandleHorizontalAxisInputEvent(float Value);
void HandleVerticalAxisInputEvent(float Value);
};
How do I see Log Output from my game? 怎么看调试输出信息?
UE4编辑器中:Window -> Developer Tools
How do I throw exceptions? 我怎么才能抛出异常错误?
UE4中没有这样的机制,而是使用check()函数。
Where is the .NET Framework? .NetFramework在哪里?
.Net Framework | UE4 |
---|---|
String | FString, FText |
List | TArray |
Dictionary | TMap |
HashSet | TSet |