11715人加入学习
(26人评价)
【旧版】Unreal基本知识案例 - 密室逃脱

旧版课程,制作完成于2017-01-11

价格 免费

shift 跟随移动

alt 复制移动

end 落地

[展开全文]

在 内容浏览器 窗口下

新建文件夹 和 导入资源

 

点击即可预览声音

 

在SM_Door_Blueprint 时间轴 添加事件轨迹

 

Play Sound at Location 播放音乐在某个位置

 

GetActorLocation 获取当前物体的位置:

 

Play Music只会在 事件关键帧 调用

 

// 总结

//所有#inclde 的头文件需要在 #include "XXXXX.generated.h"的上方

//使用 AActor* 需要使用的头文件是:GameFramework/Actor.h
//使用 ATriggerVolume* 需要引入的头文件是:Engine/TriggerVolume.h
//使用 GetWorld() 需要引入的头文件是:Engine/World.h
//使用 DrawDebugLine(GetWorld(),Start,End,FColor(255,0,0),false,0,0,10); 需要引入的头文件是:DrawDebugHelpers.h
//使用 UInputComponent* 需要引入的头文件是:Components/InputComponent.h
//使用 UPhysicsHandleComponent* 需要引入的头文件:PhysicsEngine/PhysicsHandleComponent.h
//使用 UPrimitiveComponent* 需要引入的头文件按是:Components/PrimitiveComponent.h

//通过拖拽实现的字段,需要添加 UPROPERTY(EditAnyWhere) 标识
//通过蓝图可以监听到事件,需要添加 UPROPERTY(BlueprintAssignable) 标识

// 添加事件
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDoorEvent); 

// 打印输出日志
UE_LOG(LogTemp,Warning,TEXT("Hello World!"));
UE_LOG(LogTemp,Waring,TEXT("Hello %s am in OpenDoor!"), *Owner->GetName());
UE_LOG(LogTemp,Warning,TEXT("Total Mass is %f!"),TotalMass);

 

 

 

 

[展开全文]

蓝图:

SetActorRotation

Make Rotator

按住 Ctrl 可以移动线

 

X(Roll)

Y(Pitch)

Z(Yaw)

 

代码里面是:pitch,yaw,roll 的顺序

 

Reverse 回播,动画倒着播放

 

小bug:DefaultPawn和其他物体发生碰撞,导致DefaultPawn不受控制的移动旋转

勾选DefaultPawn_Blueprint 下的 Physics 下的 约束 锁定旋转X Y Z 勾选

需要选中 CollisionComponent(继承)下找

 

[展开全文]
void UOpenDoor1::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	//if (TriggerVolume != nullptr && TriggerVolume->IsOverlappingActor(DefaultPawn))
	if (TriggerVolume && GetTotalMassInTrigger() > 25)
	{
		OnOpen.Broadcast();
		
	}
	else
	{
		OnClose.Broadcast();
	}
}

 

 

在SM_Door的蓝图

添加上OnClose()

添加时间轴

中间的白线,表示,从OnOpen函数执行到 时间轴_0

双击时间轴,可以编辑时间轴:

添加浮点型轨迹(float类型的时间轴)

添加向量型轨迹(Vector类型的时间轴)

添加事件轨迹:

添加颜色轨迹:

0-90度 的变化,可以添加浮点型轨迹

更改时间轴名称为:Angle

在第0帧,添加关键帧,右键0.00,0.00位置,添加关键帧到CurveFloat_0

添加后,多了一个黄色的菱形小点

时间从 0 开始,修改成 0

再添加关键帧,时间为1,值为90

点击这2个,使得界面融合

滚动滚轮,可以放大缩小时间轴的显示范围:

长度(时间的长度)改为:1.00

 

添加完了时间轴的曲线后,在事件图表上多了Angle和Test的显示

白线是流程,其他的线是数值

中间为什么会有这个东西,因为Angle是float 类型,Print String是 String类型,把float转换成string,自动完成的

 

单独删除某个线,按住 Alt 键,点击线即可删除

 

删除中间的转换图标,选中后,可以用BackSpace或者Delete

 

蓝图移动:

按住鼠标右键拖动,

滚动滑轮,放大缩小

[展开全文]

做动画效果,使用蓝图/代码

蓝图实现简单

 

使得自身进入机关,也触发开门效果

Simulate Physics

MassInKg

 

蓝图---转换选择的Actor为蓝图类:

转换成蓝图类后,世界大纲视图中的名字也变了,加上了_Blueprint

 

编辑蓝图类:

①:双击内容浏览器中的蓝图类(SM_Door_Blueprint)

②:在世界大纲视图中的文件后面,点击编辑 SM_Door_Blueprint

 

蓝图下的窗口:

视口(Viewport) 用于观看模型是怎么样子的

事件图表 (Event Graph)

事件图表(Event Graph)下,可以按住鼠标左键框选,右键对应的图标删除,

 

 

改成蓝图类后,上面的属性就会丢失掉:

比如下图中Trigger Volume ,需要拖拽的引用

 

 

在C++代码里面定义事件,蓝图也可以监听到

需要开门的时候,去触发事件,蓝图可以监听到事件,然后做一些事情

 

 

OpenDoor.h 头文件中

// DECLARE声明,DYNAMIC动态,MULTICAST多个,DELEGATE委托 (C# delegate 委托,Event 事件)

DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDoorEvent); // 事件加F,需要加“;”号

 

UPROPERTY(BlueprintAssignable) // 使用这个“注释”,可以使得下面2个在蓝图可以识别到

FDoorEvent OnOpen;

FDoorEvent OnClose;

 

代码定义好了,蓝图 添加事件才会有对于的OnOpen

 

添加了,事件就在我的蓝图窗口---图表显示了,OnOpen(OpenDoor)

 

 

取消添加,再添加引用,解决没有问题的报错

 

箭头可以拖出来

 

 

Print String 打印字符串

 

C++代码触发,蓝图监听

蓝图也要编译和保存

 

蓝图也可以播放

 

//OpenDoor.h 文件

// DECLARE声明,DYNAMIC动态,MULTICAST多个,DELEGATE委托 (C# delegate 委托,Event 事件)
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDoorEvent); // 事件加F,需要加“;”号

public:
	UOpenDoor();
	UPROPERTY(BlueprintAssignable) // 使用这个“注释”,可以使得下面2个在蓝图可以识别到,蓝图可编辑的意思
	FDoorEvent OnOpen;
	UPROPERTY(BlueprintAssignable)
	FDoorEvent OnClose;



// UOpenDoor.cpp 文件
void UOpenDoor::OpenDoor()
{
	// 得到所在的Actor  设置这个Actor的属性
	// pitch=y  yaw=z  roll=x
	FRotator NewRotator = FRotator(0, 90, 0);
	Owner->SetActorRotation(NewRotator);
	OnOpen.Broadcast(); // C++触发这个事件,蓝图监听事件
}

 

[展开全文]

设置椅子和桌子的质量

细节面板上的Physics---MassInKg打勾并设置质量

 

报错是因为没有引入 UPrimitiveComponent 所需要的头文件

#include "Components/PrimitiveComponent.h"
TotalMass += Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();

UE_LOG(LogTemp, Warning, TEXT("Total Mass is %f!"), TotalMass);// 加 * 号是取指针的数据,%f 对于小数类型,直接写小数就行,和C语言printf()一样

为什么显示还是质量0,因为没有勾选上 Generate Overlap Events

检测方式要一致:代码:TriggerVolume->GetOverlappingActors(OUT Actors) 与 Generater Overlap Events 对应

主角没有重力,勾选上 Simulate Physics

Physics---Simulate Physics,勾选上就会有重力的效果

#include "Components/PrimitiveComponent.h"

void UOpenDoor1::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	//if (TriggerVolume != nullptr && TriggerVolume->IsOverlappingActor(DefaultPawn))
	if (TriggerVolume && GetTotalMassInTrigger() > 25)
	{
		OpenDoor();
		LastDoorOpenTime = GetWorld()->GetTimeSeconds();
	}
	if (GetWorld()->GetTimeSeconds() - LastDoorOpenTime > DoorOpenDuration)
	{
		CloseDoor();
	}

}


float UOpenDoor1::GetTotalMassInTrigger()
{
	TArray<AActor*> Actors;
	if (TriggerVolume == nullptr)
		return 0.0f;
	TriggerVolume->GetOverlappingActors(OUT Actors);// OUT 在语法上没有任何影响,方便阅读代码的

	float TotalMass = 0;
	for (AActor* Actor : Actors)// for(const auto& Actor : Actors)
	{
		TotalMass += Actor->FindComponentByClass<UPrimitiveComponent>()->GetMass();
	}
	UE_LOG(LogTemp, Warning, TEXT("Total Mass is %f!"), TotalMass);// 加 * 号是取指针的数据,%f 对于小数类型,直接写小数就行,和C语言printf()一样
	return TotalMass;
}

[展开全文]

一直抓取着,在TickComponent中

// Called every frame
void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
	if (PhysicsHandle&&PhysicsHandle->GrabbedComponent)
	{
		PhysicsHandle->SetTargetLocation(GetLineEnd());
	}
}


void UGrabber::Grab()
{
	UE_LOG(LogTemp, Warning, TEXT("Grab action is pressed!"));
	FHitResult Hit = LineTrace();
	UPrimitiveComponent* ComponentToGrab = Hit.GetComponent();
	if (Hit.GetActor() && PhysicsHandle)
	{
		UE_LOG(LogTemp, Warning, TEXT("Grab!"));
		//PhysicsHandle->GrabComponent(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), true);
		PhysicsHandle->GrabComponentAtLocationWithRotation(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), GetOwner()->GetActorRotation());
	}
}


void UGrabber::Release()
{
	UE_LOG(LogTemp, Error, TEXT("Grab action is released!"));
	if (PhysicsHandle)
	{
		PhysicsHandle->ReleaseComponent();
	}
}

 

[展开全文]

给 DefaultPawn_Blueprint 添加组件 Phusics Handle

 

(对蓝图做的修改都要保存和编译)添加完组件后,需要 Save 和 编译

 

使用Physics Handle 需要引入的头文件 #include "PhysicsEngine/PhysicsHandleComponent.h"

 

不知道用头文件,使用谷歌搜索一下,看官方的文档里面找

使用 UPhysicsHandleComponent* ,需要引入头文件 #include "PhysicsEngine/PhysicsHandleComponent.h"

没有引入组件导致的报错:

引入#include "Components/PrimitiveComponent.h"

使用UPrimitiveComponent* 需要引入 #include "Components/PrimitiveComponent.h"

 

没有抓起来,Actor是 可移动的

// Grabber.h
#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/InputComponent.h"
#include "PhysicsEngine/PhysicsHandleComponent.h"
#include "Grabber.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UNREALENGINEPROJECT_API UGrabber : public UActorComponent
{
	GENERATED_BODY()

public:	
	UGrabber();

protected:
	virtual void BeginPlay() override;

public:	
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

private:
	FVector GetLineStart();
	FVector GetLineEnd();
	FHitResult LineTrace();
	UInputComponent* InputComponent = nullptr;
	UPhysicsHandleComponent* PhysicsHandle = nullptr;
	void Grab();
	void Release();
};

// Grabber.cpp


#include "Grabber.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"
#include "Components/PrimitiveComponent.h"

UGrabber::UGrabber()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void UGrabber::BeginPlay()
{
	Super::BeginPlay();

	PhysicsHandle = GetOwner()->FindComponentByClass<UPhysicsHandleComponent>();

	InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();

	if (InputComponent)// 使用指针需要判断不为空
	{
		UE_LOG(LogTemp, Warning, TEXT("Input Component is founded!"));
		InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
		InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Input Component is not founded!"));
	}
	
}


void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

FVector UGrabber::GetLineStart()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return Start;
}

FVector UGrabber::GetLineEnd()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return (Start + ViewRotator.Vector() * 100); // ViewRotator.Vector() 视野的正中心 前方 100cm
}

FHitResult  UGrabber::LineTrace()
{
	//DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);

	FHitResult Hit;
	GetWorld()->LineTraceSingleByObjectType(
		Hit,
		GetLineStart(),
		GetLineEnd(),
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		FCollisionQueryParams(FName(TEXT("")), false, GetOwner())
	);
	AActor* Actor = Hit.GetActor();
	if (Actor != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Line Hit:%s"), *Actor->GetName());
	}
	return Hit;
}

void UGrabber::Grab()
{
	UE_LOG(LogTemp, Warning, TEXT("Grab action is pressed!"));
	FHitResult Hit = LineTrace();
	UPrimitiveComponent* ComponentToGrab = Hit.GetComponent();
	if (Hit.GetActor() && PhysicsHandle)
	{
		UE_LOG(LogTemp, Warning, TEXT("Grab!"));
		//PhysicsHandle->GrabComponent(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation(), true); // 已弃用
		PhysicsHandle->GrabComponentAtLocation(ComponentToGrab, NAME_None, ComponentToGrab->GetOwner()->GetActorLocation());
	}
}

void UGrabber::Release()
{
	UE_LOG(LogTemp, Error, TEXT("Grab action is released!"));
}

 

[展开全文]

编辑---项目设置---引擎--输入

Bindings

Action Mappings(某个键的按下)

Axis Mappings(某个轴的按下)

 

 

2个大步骤:

(1)在编辑---项目设置---引擎--输入-Bindings-Action Mappings(某个键的按下),添加事件再添加需要触发的按键

(2)写代码

 

 

 

添加上以后,运行场景系统在DefaultPawn_Blueprint的细节面板上有PawnInputComponent(继承):

 

 

 

#include "Components/InputComponent.h"

#include "Grabber.generated.h" // 引入的头文件需要再这个头文件的前面

UInputComponent* InputComponent = nullptr;

使用 UInputComponent* 需要引入 #include "Components/InputComponent.h"

 

 

 

// Grabber.h

#pragma once

#include "CoreMinimal.h"
#include "Components/ActorComponent.h"
#include "Components/InputComponent.h"
#include "Grabber.generated.h"


UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class UNREALENGINEPROJECT_API UGrabber : public UActorComponent
{
	GENERATED_BODY()
public:	
	UGrabber();
protected:
	virtual void BeginPlay() override;
public:	
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;

private:
	FVector GetLineStart();
	FVector GetLineEnd();
	AActor* LineTrace();
	UInputComponent* InputComponent = nullptr;
	void Grab();
	void Release();
};

 

 

// Grabber.cpp

#include "Grabber.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"


UGrabber::UGrabber()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void UGrabber::BeginPlay()
{
	Super::BeginPlay();
	InputComponent = GetOwner()->FindComponentByClass<UInputComponent>();

	if (InputComponent)// 使用指针需要判断不为空
	{
		UE_LOG(LogTemp, Warning, TEXT("Input Component is founded!"));
		InputComponent->BindAction("Grab", IE_Pressed, this, &UGrabber::Grab);
		InputComponent->BindAction("Grab", IE_Released, this, &UGrabber::Release);
	}
	else
	{
		UE_LOG(LogTemp, Error, TEXT("Input Component is not founded!"));
	}
	
}


void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

FVector UGrabber::GetLineStart()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return Start;
}

FVector UGrabber::GetLineEnd()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return (Start + ViewRotator.Vector() * 100); // ViewRotator.Vector() 视野的正中心 前方 100cm
}

AActor * UGrabber::LineTrace()
{
	//DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);

	FHitResult Hit;
	GetWorld()->LineTraceSingleByObjectType(
		Hit,
		GetLineStart(),
		GetLineEnd(),
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		FCollisionQueryParams(FName(TEXT("")), false, GetOwner())
	);
	AActor* Actor = Hit.GetActor();
	if (Actor != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Line Hit:%s"), *Actor->GetName());
	}
	return Actor;
}

void UGrabber::Grab()
{
	UE_LOG(LogTemp, Warning, TEXT("Grab action is pressed!"));
}

void UGrabber::Release()
{
	UE_LOG(LogTemp, Error, TEXT("Grab action is released!"));
}

 

[展开全文]

if(Actor != nullptr)

if(Actor)

效果一样

指针、对象 也好,都可以这样判断不为空执行if语句

 

#include "Grabber.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"


UGrabber::UGrabber()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void UGrabber::BeginPlay()
{
	Super::BeginPlay();
}


void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

FVector UGrabber::GetLineStart()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return Start;
}

FVector UGrabber::GetLineEnd()
{
	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);
	return (Start + ViewRotator.Vector() * 100); // ViewRotator.Vector() 视野的正中心 前方 100cm
}

AActor * UGrabber::LineTrace()
{
	//DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);

	FHitResult Hit;
	GetWorld()->LineTraceSingleByObjectType(
		Hit,
		GetLineStart(),
		GetLineEnd(),
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		FCollisionQueryParams(FName(TEXT("")), false, GetOwner())
	);
	AActor* Actor = Hit.GetActor();
	if (Actor != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Line Hit:%s"), *Actor->GetName());
	}
	return Actor;//Actor 可能为空,需要校验
}

 

[展开全文]

射线检测:有起点有方向有距离

ECC_PhysicsBody 物理物体

细节面板上的 Physics ,勾选 Simulate Physics 才会触发碰撞,

射线触发一定要勾选上 细节面板上的Physics下的 Simulate Physics 才会触发

 

Grabber.cpp

#include "Grabber.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"


UGrabber::UGrabber()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void UGrabber::BeginPlay()
{
	Super::BeginPlay();
}


void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);

	FVector End = Start + ViewRotator.Vector() * 100; // ViewRotator.Vector() 视野的正中心 前方 100cm

	//DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);

	FHitResult Hit;
	GetWorld()->LineTraceSingleByObjectType(
		Hit,
		Start,
		End,
		FCollisionObjectQueryParams(ECollisionChannel::ECC_PhysicsBody),
		FCollisionQueryParams(FName(TEXT("")), false, GetOwner())
	);
	AActor* Actor = Hit.GetActor();
	if (Actor != nullptr)
	{
		UE_LOG(LogTemp, Warning, TEXT("Line Hit:%s"), *Actor->GetName());
	}
}

 

[展开全文]

 

添加抓取功能:

在DefaultPawn_Blueprint文件中:

添加组件---新建C++组件...

 

第二步,选择Actor Component :

第三步,名称改称为Grabber,抓取器:

创建类

 

Unreal Engine 4 中的坐标/向量 FVector

FVector Start;

 

获取PlayerController()

#include "Engine/World.h"

GetWorld()->GetFirstPlayerController()

 

 

 

PlayerController : 控制Player的移动的

 

 

 

使用DrawDebugLine

需要引用 #include "DrawDebugHelpers.h"

DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);

 

API

void DrawDebugLine()
{
    const UWorld * InWorld,
    FVector const & LineStart,
    FVector const & LineEnd,
    FColor const & Color,
    bool bPersistentLines;
    float LifeTime,
    uint8 DepthPriority,
    float Thickness
}

编译没看到线,先保存一下蓝图类DefaultPawn_Blueprint !!!

 

#include "Grabber.h"
#include "Engine/World.h"
#include "DrawDebugHelpers.h"


UGrabber::UGrabber()
{
	PrimaryComponentTick.bCanEverTick = true;
}


void UGrabber::BeginPlay()
{
	Super::BeginPlay();	
}


void UGrabber::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	FVector Start;
	FRotator ViewRotator;
	GetWorld()->GetFirstPlayerController()->GetPlayerViewPoint(Start, ViewRotator);

	FVector End = Start + ViewRotator.Vector()*100; // ViewRotator.Vector() 视野的正中心 前方 100cm

	DrawDebugLine(GetWorld(), Start, End, FColor(255, 0, 0), false, 0, 0, 10);
}

 

[展开全文]

选中物体后,

工具栏---蓝图---转换选择的Actor为蓝图类

Toolbar

Blueprints---Convert Selected Actor to Blueprint Class

 

创建的DefaultPawn_Blueprint

 

编辑---项目设置---地图和模式

Edit---Project Settings---Maps & Modes

Create New Blueprints

 

选择我们自定义的DefaultPawn_Blueprint

 

内容浏览器下有NewGameMode

[展开全文]
// 日志输出:临时日志,警告级别,文字,%s,替换,加 * 表示取得数据
UE_LOG(LogTemp, Warning, TEXT("Hello %s am in OpenDoor! "), *Owner->GetName());
// GetName() 取得是ID名称

输出日志 窗口:

窗口---开发者工具---输出日志

 

[展开全文]

使用指针前,需要判断指针不能为空,否则容易崩溃

TriggerVolume != nullptr

 

指针:

指针!=nullptr

 

private:
    AActor* Owner;
    UPROPERTY(EditAnyWhere)
    ATriggerVolume* TriggerVolume;

    AActor* DefaultPawn;

    float DoorOpenDuration = 0.5f;
    float LastDoorOpenTime = 0;

 

 

void UOpenDoor1::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
    Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
    if (TriggerVolume != nullptr && TriggerVolume->IsOverlappingActor(DefaultPawn))
    {
        OpenDoor();
        LastDoorOpenTime = GetWorld()->GetTimeSeconds();
    }
    if (GetWorld()->GetTimeSeconds() - LastDoorOpenTime > DoorOpenDuration)
    {
        CloseDoor();
    }

}

 

[展开全文]

运行时:

白色:本来存在的

黄色:运行时候生成的

 

DefaultPawn 默认创建的角色

 

Shift + F1 鼠标脱离场景

F8 弹出:同玩家控制器分离,允许正常的编辑器控制

 

每次修改完代码要编译一下

 

 

使用GetWorld()需要引入库:#include “Engine/World.h”

使用ATriggerVolume需要引入库:#include "Engine/TriggerVolume.h"

 

[展开全文]

这三个文件夹不能删除:Config、Content、Source

 

这些文件夹及文件都能删除:.vs、Binaries、Intermediate、Saved、UnrealEngineProject.sln

 

重新打开,需要重新生成,点“是”

 

Content、Source不能删除

 

 

属性的初始化放在BeginPlay()

[展开全文]

Actor的相关的,都是A开头的

AAcotr*

ATriggerVolume*

 

所有的引入的,需要放在generated.h的上方

由于这个报错:

所以添加引用:

 

通过拖拽的方法实现:

需要加入UPROPERTY(EditAnyWhere)

 

锁定 图标的用处,便于拖拽

[展开全文]

光照---聚光灯

Lights---Spot Light

Light:

Inner Core Angle

Outer Cone Angle

体积--Trigger Volume

Volumes---Trigger Volume:

 

LIGHTING NEEDS TO BE REBUILT(1 unbuilt object)

Build---Build Light Only

构建---仅构建光照

[展开全文]

笛卡尔坐标系---维基百科

二维坐标:

三维坐标:

向量/坐标

单位化

世界坐标系

局部坐标系

 

[展开全文]

授课教师

SiKi学院老师

课程特色

图文(2)
视频(37)