调试
- 在当前屏幕视口中打印
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT(“Hello”));首参数-1,表示无需更新或刷新此消息,第二个参数表示持续时间2. 在编辑器output log窗口中输出UE_LOG(LogTemp, Log, TEXT(“Your message”));第一个参数 ---- Log的类别。 LogTemp 是 Log 的类别 中的一种。第二个参数 ---- Log的颜色 。Warning , 表示输出信息用Yellow黄色来显示,Log,表示输出信息用 Grey 灰色来显示,Error,表示输出信息用 Red 红色来显示第三个参数 ---- TEXT(“信息”)3.在编辑器中打开输出日志的方法,窗口-开发者工具-输出日志4.输出可变量UE_LOG(LogTemp, Log,TEXT(" %s ,%f,%i") , StringName , float, int); %s 是输出 字符串,注意加%f 是输出 浮点数数字,比如 time 就是 float 类型的%i 是 int 类型
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]
基本处理
创建一个继承actor的类
#pragma once
#include “GameFramework/Actor.h”
#include “MyActor.generated.h”
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
int Count;
// 为此Actor的属性设置默认值。
AMyActor()
{
// Allows Tick() to be called
PrimaryActorTick.bCanEverTick = true;
}
// 当游戏开始或此Actor生成时调用。
void BeginPlay()
{
Super::BeginPlay();
Count = 0;
}
// 每帧调用。
void Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
Count = Count + 1;
GLog->Log(FString::FromInt(Count));
}
// 当此Actor销毁时调用。
void EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason)
}
};
创建一个actor类的组件
UCLASS()
class UMyComponent : public UActorComponent
{
GENERATED_BODY()
// 当所属Actor创建时调用 void InitializeComponent(); // 当组件或所属Actor销毁时调用 void UninitializeComponent(); // 组件版的Tick函数 void TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction);
};
根据不同的需要,你需要用一些不同的函数来实例化对象。
NewObject 用于新建 UObject 类型的实例,
SpawnActor 用于新建 AActor 类型的实例
CreateDefaultSubobject可以创建组件并赋予组件默认值
销毁整体对象:MyActor->Destroy();
销毁整体对象,1秒延迟:MyActor->SetLifeSpan(1);
失活一个整体对象:
MyActor->SetActorHiddenInGame(true);
// Disables collision components
MyActor->SetActorEnableCollision(false);
// Stops the Actor from ticking
MyActor->SetActorTickEnabled(false);
通过组件访问其所属整体对象:
AActor* ParentActor = MyComponent->GetOwner();
通过整体对象访问其所具有组件:
UMyComponent* MyComp = MyActor->FindComponentByClass();
查找指定的整体对象:
// Find Actor by name (also works on UObjects)
AActor* MyActor = FindObject(nullptr, TEXT(“MyNamedActor”));
// Find Actors by type (needs a UWorld object)
for (TActorIterator It(GetWorld()); It; ++It)
{
AMyActor* MyActor = *It;
// …
}
// Find UObjects by type
for (TObjectIterator It; It; ++It)
{
UMyObject* MyObject = *It;
// …
}
// Find Actors by tag (also works on ActorComponents, use TObjectIterator instead)
for (TActorIterator It(GetWorld()); It; ++It)
{
AActor* Actor = *It;
if (Actor->ActorHasTag(FName(TEXT(“Mytag”))))
{
// …
}
}
为整体对象添加标签:
MyGameObject.tag = “MyTag”;
// Actors can have multiple tags
MyActor.Tags.AddUnique(TEXT(“MyTag”));
为组件添加标签:
// This changes the tag on the GameObject it is attached to
MyComponent.tag = “MyTag”;
// Components have their own array of tags
MyComponent.ComponentTags.AddUnique(TEXT(“MyTag”));
比较标签:
if (MyGameObject.CompareTag(“MyTag”))
{ // … }
// Checks the tag on the GameObject it is attached to
if (MyComponent.CompareTag(“MyTag”))
{ // … }
// Checks if an Actor has this tag
if (MyActor->ActorHasTag(FName(TEXT(“MyTag”))))
{ // … }
// Checks if an ActorComponent has this tag
if (MyComponent->ComponentHasTag(FName(TEXT(“MyTag”))))
{
// …
}
碰撞检测
在 Unity 中,假如要给一个 GameObject 赋予物理特性,需要给它添加一个刚体组件。在虚幻中,任何图元组件(C++ 中为 UPrimitiveComponent)都可以是物理对象。一些通用的图元组件,比如 ShapeComponent(胶囊形,球形,盒形),StaticMeshComponent,以及 SkeletalMeshComponent。
和 Unity 不同,Unity 将碰撞和可视性划分到不同的组件中。而虚幻则将潜在的物理碰撞和潜在的可视效果组合到了 PrimitiveComponent 中。任何在世界中具有形状的物体,要么就是能够被渲染显示,要么就是能和继承自 PrimitiveComponent 的物理子类交互。
射线检测,从摄像机出发,往场景发出射线,随后检测碰撞情况
碰撞检测中,通道的概念,其实可以类比成一种逻辑层级,都这一层级下才发生影响
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(Hit.Actor.Get());
}
return nullptr;
}
触发器效果:
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
// My trigger component
UPROPERTY()
UPrimitiveComponent* Trigger;
AMyActor()
{
Trigger = CreateDefaultSubobject(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);
}
virtual void NotifyActorBeginOverlap(AActor* Other) override;
virtual void NotifyActorEndOverlap(AActor* Other) override;
};
刚体运动
在虚幻 4 中,碰撞组件和刚体组件是同一个组件,
它的基类是 UPrimitiveComponent,
这个基类有很多不同的子类(USphereComponent,UCapsuleComponent 等)
来配合不同的需求。
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
UPROPERTY()
UPrimitiveComponent* PhysicalComp;
AMyActor()
{
PhysicalComp = CreateDefaultSubobject(TEXT("CollisionAndPhysics"));
PhysicalComp->SetSimulatePhysics(false);
PhysicalComp->SetPhysicsLinearVelocity(GetActorRotation().Vector() * 100.0f);
}
};
容器
虚幻 4 并不使用 .NET Framework。
虚幻 4 有自己的一套容器类和库。常见的容器来对照:
String——>Fstring、FText
List——>TArray
Dictionary——>TMap
HashSet——>TSet
[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]
输入响应
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);
};



