UE4 Scripting with C++_02

墨墨昧昧,其光必远。

有些问题在书本中并不能找到答案。

这一节参考英文教程Packt Publishing - Basics of Coding with Unreal Engine 4,使用第三人称C++模板进行实例测试,正好补充上一节中所没有处理的问题。

1)、使用UE_LOG打印人物起跳次数

    重写Jump函数,创建存储起跳次数的变量
    virtual void Jump() override;
    void AUnrealScriptingBasicCharacter::Jump()
    {
        Super::Jump();
        UE_LOG(LogTemp, Warning, TEXT("Player is Jumping"));
        JumpTimes++;
        FString JumpsText = FString::Printf(TEXT("The Player has jumped %d times..."),JumpTimes);
        UE_LOG(LogTemp, Warning, TEXT("%s"), *JumpsText);
    }



2)Actor的创建,设置Component,与实例化Actor

先给代码,再分析要点

为MagicPill赋予一个StaticMeshComponent

1)、MagicPill.h
UCLASS()
class UNREALSCRIPTINGBASIC_API AMagicPill : public AActor
{
	GENERATED_BODY()	
public:	
	// Sets default values for this actor's properties
	AMagicPill();
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	//My added items to the class
protected:
	//the amount of health that the pill has
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Values")
	float PillEffect;
public:
	UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Components")
	UStaticMeshComponent* PillMesh;	
};

这里主要创建两个EditAnyWhere成员变量,其中一个是StaticMesh,用于在场景中显示
2)、MagicPill.c
// Sets default values
AMagicPill::AMagicPill()
{
	PillEffect = 0.0f;
	PillMesh = CreateDefaultSubobject<UStaticMeshComponent>("BaseMeshComponent");
	auto MeshAsset = ConstructorHelpers::FObjectFinder<UStaticMesh>
(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_NarrowCapsule.Shape_NarrowCapsule'"));
		if (MeshAsset.Object != nullptr)
		{
			PillMesh->SetStaticMesh(MeshAsset.Object);
		}
}

// Called when the game starts or when spawned
void AMagicPill::BeginPlay()
{
	Super::BeginPlay();
	PillMesh->SetSimulatePhysics(true);
}
这里用于初始化成员变量并且设置仿真物理模拟

创建一个PillSpawner用于动态生成MagicPill对象

创建PillSpawner
protected:
	UPROPERTY(EditAnywhere,Category="Spawning")
	TSubclassOf<class AMagicPill> ItemToSpawn;
	
private:
        UFUNCTION(BlueprintPure , Category="Spawning")
	FVector GetRandomPointInVolume();
	UPROPERTY(VisibleAnyWhere,BlueprintReadOnly,Category="Spawning",meta=(AllowPrivateAccess="true"))
	class UBoxComponent* SpawningVolume;
	//this function will spawn pills
	void SpawnPills();

想要实例化对象首先使用TSubClassof说明要实例化的对象类型

创建SpanPills方法用于实例化操作
PillSpawner.cpp
#include "UnrealScriptingBasic.h"
#include "PillSpawner.h"
#include "MagicPill.h"
#include "Classes/Kismet/KismetMathLibrary.h"
// Sets default values
APillSpawner::APillSpawner()
{
	SpawningVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolumeBox"));
	RootComponent = SpawningVolume;
	//this establishes the the item to spawn 
	ItemToSpawn = AMagicPill::StaticClass();
}
// Called when the game starts or when spawned
void APillSpawner::BeginPlay()
{
	Super::BeginPlay();
	SpawnPills();
}
//This is the function returns a random point int the volume
FVector APillSpawner::GetRandomPointInVolume()
{
	FVector Origin = SpawningVolume->Bounds.Origin;
	FVector Extent = SpawningVolume->Bounds.BoxExtent;
	return UKismetMathLibrary::RandomPointInBoundingBox(Origin, Extent);
}

void APillSpawner::SpawnPills()
{
	if (ItemToSpawn != NULL)
	{
		UWorld* const World = GetWorld();
		if (World) {
			FVector SpawnLocation = GetRandomPointInVolume();
			FRotator SpawnRotation;
			SpawnRotation.Pitch = FMath::FRand()*360.f;
			SpawnRotation.Roll = FMath::FRand()*360.f;
			SpawnRotation.Yaw = FMath::FRand()*360.f;
			AMagicPill* SpawnedPill = World->SpawnActor<AMagicPill>(ItemToSpawn, SpawnLocation, SpawnRotation);
		}
	}
}

涉及要点有三:

1)、Actor中的Component设置
和蓝图类似,蓝图类中的component类型都可以添加

2)、定义和蓝图以及UE4Editor的交互
UPROPERTY设置变量的交互
UFUNCTION设置函数的交互
注意到一个事,无论是udemy等国外的教程中都是使用C++创建一个基类,
具备基本的要素(StaticMesh,TriggerVolume,Varibles等),再使用基于C++类派生的
蓝图类进行细化这些要素,staticmesh具体长什么样,TriggerVolume该有多大,Varible的具体值等
很少直接把C++的Actor直接放到场景之中。
总结就是C++类定义数据和行为,蓝图来细化这些数据和行为,十分像多态的行为。

3)、类对象的实例化,体现反射机制
主要需要记忆的是格式:
我要实例化什么?--通过Tsubclassof
        UPROPERTY(EditAnywhere,Category="Spawning")
        TSubclassOf<class AMagicPill> ItemToSpawn;
我怎么初始化?--通过StaticClass()
	//this establishes the the item to spawn 
	ItemToSpawn = AMagicPill::StaticClass();
怎么样在场景中实例化?--UWorld的SpawnActor方法
        UWorld* const World = GetWorld();
	if (World) {
	FVector SpawnLocation = GetRandomPointInVolume();
	FRotator SpawnRotation;
	SpawnRotation.Pitch = FMath::FRand()*360.f;
	SpawnRotation.Roll = FMath::FRand()*360.f;
	SpawnRotation.Yaw = FMath::FRand()*360.f;
	AMagicPill* SpawnedPill = World->SpawnActor<AMagicPill>(ItemToSpawn, SpawnLocation, SpawnRotation);
		}

3)、内存管理

内存管理对于一个高效并且没有bug的程序是一件十分重要的工作,包含常规操作和UE4提供的智能指针

1)、malloc和free
    int * JumpHeight; //声明指针变量
    JumpHeight=(int*)malloc(Sizeof(int));//分配空间
    *JumpHeight=10; //指针变量赋值
    FString jumpheightText=FString::Printf(TEXT("The Player jumps %d up in the air.")
,JumpHeight);
    UE_LOG(Log_Temp,Warning,TEXT("%s"),*jumpheightText);
    free(JumpHeight); //释放指针所指向的内存空间
    JumpHeight=0; //指针赋值为空
2)、new和delete
    int * JumpHeight; //声明指针变量
    JumpHeight=new int();//分配空间
    *JumpHeight=10; //指针变量赋值
    FString jumpheightText=FString::Printf(TEXT("The Player jumps %d up in the air.")
,JumpHeight);
    UE_LOG(Log_Temp,Warning,TEXT("%s"),*jumpheightText);
    delete JumpHeight; //释放指针所指向的内存空间
    JumpHeight=0; //指针赋值为空
   如果是对象的动态创建,new会调用构造函数,delete会调用析构函数 
3)、UObject或是AActor提供了动态内存处理机制
    SpawnActor<>用来创建AActor
    NewObject<>  ConstructObject<>用来创建UObject

4)、TSharedPtr的使用:

    class MyClass{
        int values;
    };
    TSharedPtr<MyClass> emptySharedClass;//this is an Empty shared
    TSharedPtr<MyClass> firstSharedObject<New MyClass());//声明和初始化shredptr
    TSharedPtr<MyClass> anotherObj=firstSharedObject;
    if(firstSharedObject.IsValid()){//通过IsValid方法判断指针非空}
    通过sharedptr访问内存,类似于常规指针,sharedptr会自动释放

5)、Garbage Collection使用了反射机制,关于C++的反射机制,等我学通后再梳理一遍

要想使用UE4中的垃圾收集系统:
使用UPROPERTY的类成员将会使用动态的内存管理
只使用基于UObject的类型或者是智能指针。
强制进行垃圾收集:
GetWorld()->ForceGabageCollection(true);

至此,相应的初级code视频教程内容也结束了,后续还有中级code和高级的code视频

接下来一篇仍然是看书做笔记,遇到问题后再看相关视频找如何解决

猜你喜欢

转载自blog.csdn.net/weixin_33232568/article/details/88659391