暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

虚幻UnrealEngine4 C++ Actor类&物理

林元皓 2020-02-23
1436

Unreal Engine 中类前缀规则

之前,我们建立了第一个继承 Object 的类,这里首先看一下 Unreal Engine 中类的前缀规则。

  1. 派生自 Actor 的类带有 A 前缀,如 AOneActor

  2. 派生自 Object 的类带有 U 前缀,如 AOneObject

  3. Enums 的前缀是 E,如 EOneType

  4. Interface 的前缀通常是 I,如 IOneInterface

  5. Template 的前缀是 T,如 TArray

  6. 派生自 SWidget 的类(Slate UI)带有前缀 S,如 SButton

  7. 结构体、其他类的前缀为字母 F,如 FVertor



C++和蓝图中创建继承 Actor 的类

Unreal 的坐标系和单位

在工程中,导入一个坐标系模型,以方便理解 UE4 的坐标系跟单位。人物模型身高 1.8米 左右。

  • UE4 缺省坐标系统为左手坐标系统,x向后,y向右,z向上

  • 每一个Unreal单位,对应现实单位1厘米,100就是1米。

C++ 中的创建继承 Actor 的类 OneActor

  • 创建 继承于 Actor 的类 OneActor 开始我们正题,创建一个类名为 OneActor 的类,让其继承于 Actor。注意,在 UE4 引擎中,无法创建 VS 工程中的代码文件夹,这里我们创建 OneActor 新类时,多给定了新的 Actor 文件夹目录,这样就实现了代码文件夹的创建。


创建继承 OneActor 的蓝图类 BP_OneActor

  • 跟 OneObject 不同,OneActor 可以直接创建蓝图类


  • 创建 BP_OneActor 蓝图类,继承于 OneActor


虚幻4 几个常用属性说明

  1. BlueprintReadWriteThis property can be read or written from a Blueprint. This operator is incompatible with the BlueprintReadOnly specifier.

  2. BlueprintReadWrite:在蓝图(节点)里面可以读写(getset方法)。


  3. BlueprintReadOnlyThis property can be read by Blueprints, but not modified. This operator is incompatible with the BlueprintReadWrite specifier.

  4. BlueprintReadOnly:在蓝图(节点)里面只读。


  5. EditAnywhereIndicates that this property can be edited by property windows, on archetypes and instances.

  6. EditAnywhere:在资源和实例的属性窗口都可以编辑。与Visible*标识符冲突。


  7. EditDefaultsOnlyIndicates that this property can be edited by property windows, but only on archetypes. This operator is incompatible with the Visible* specifiers.

  8. EditDefaultsOnly:只能在资源的属性窗口编辑。与Visible*标识符冲突。


  9. EditInstanceOnlyIndicates that this property can be edited by property windows, but only on instances, not on archetypes. This operator is incompatible with the Visible* specifiers.

  10. EditDefaultsOnly:只能在实例的属性窗口编辑。与Visible*标识符冲突。


  11. VisibleAnywhereIndicates that this property is visible in property windows, but cannot be edited at all. This operator is incompatible with the Edit* specifiers.

  12. VisibleAnywhere:在资源和实例的属性窗口可视,但不可编辑。与Edit*冲突。


  13. VisibleDefaultsOnlyIndicates that this property is only visible in property windows for archetypes, and cannot be edited. This operator is incompatible with the Edit* specifiers.

  14. VisibleDefaultsOnly:在资源的属性窗口可视,但不可编辑。与Edit*冲突。


  15. VisibleInstanceOnlyIndicates that this property is only visible in property windows for instances, not for archetypes, and cannot be edited. This operator is incompatible with the Edit* specifiers.

  16. VisibleDefaultsOnly:在实例的属性窗口可视,但不可编辑。与Edit*冲突。


虚幻4 常用属性的不同之处

  • 我们先编写代码,给各个变量指定不同的属性

  1. #pragma once


  2. #include "CoreMinimal.h"

  3. #include "GameFramework/Actor.h"

  4. #include "OneActor.generated.h"


  5. UCLASS()

  6. class UECPPBASICPROJECT_API AOneActor : public AActor

  7. {

  8. GENERATED_BODY()


  9. public:

  10. // Sets default values for this actor's properties

  11. AOneActor();


  12. // EditAnywhere:在资源和实例的属性窗口都可以编辑。与Visible*标识符冲突。

  13. UPROPERTY(VisibleAnywhere, Category = "One Actor Components")

  14. UStaticMeshComponent* OneStaticMesh; // 网格模型


  15. // EditDefaultsOnly:只能在实例的属性窗口编辑。与Visible*标识符冲突。

  16. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Vector")

  17. FVector InitLocation; // 游戏开始时 初始化位置


  18. // VisibleDefaultsOnly:在实例的属性窗口可视,但不可编辑。与Edit*冲突。

  19. UPROPERTY(VisibleInstanceOnly, Category = "One Actor Properties | Vector")

  20. FVector PlacedLocation; // UE4 编辑器中 放置的位置


  21. // EditDefaultsOnly:只能在资源的属性窗口编辑。与Visible*标识符冲突。

  22. UPROPERTY(EditDefaultsOnly, Category = "One Actor Properties | Vector")

  23. bool bGotoInitLocation; // 是否 编辑器放置的位置 移动到 初始位置


  24. // VisibleDefaultsOnly:在资源的属性窗口可视,但不可编辑。与Edit*冲突。

  25. UPROPERTY(VisibleDefaultsOnly, Category = "One Actor Properties | Vector")

  26. FVector WorldOrigin; // 世界原地坐标


  27. // ClampMin、 ClampMax 设置 TickLocoationOffset 的大小范围。

  28. // UIMin、 UIMax 在UI中体现出 大小范围。

  29. UPROPERTY(EditAnywhere, Category = "One Actor Properties | Vector", meta=(ClampMin=-5.0f, ClampMax=5.0f, UIMin=-5.0f, UIMax=5.0f))

  30. FVector TickLocationOffset; // Tick时 移动位置偏移大小。


  31. UPROPERTY(EditAnywhere, Category = "One Actor Properties | Vector")

  32. bool bCanTickMove; // 是否在Tick中移动


  33. protected:

  34. // Called when the game starts or when spawned

  35. virtual void BeginPlay() override;


  36. public:

  37. // Called every frame

  38. virtual void Tick(float DeltaTime) override;


  39. };

  • 双击 BP_OneActor,打开蓝图编辑器。指定一个多边形模型。搜索查看"One Actor Properties"。


  • 编辑好 BP_OneActor 相关属性后,将 BP_OneActor 蓝图拖放在 UE4 编辑器中,搜索查看"One Actor Properties"。


  • 通过说明、代码和图片的标注,对UE4中的反射,应该有了一定的了解~~


BP_OneActor 的物理

  • IcoSphere 添加碰撞 如果要对蓝图 BP_OneActor 有物理效果,首先应该对 IcoSphere 这个多边形模型添加碰撞。双击模式,进入模型编辑,生成一个简单的凸包碰撞。


  • BP_OneActor 添加物理


  • 编写代码,添加力和力矩

  1. #pragma once


  2. #include "CoreMinimal.h"

  3. #include "GameFramework/Actor.h"

  4. #include "OneActor.generated.h"


  5. UCLASS()

  6. class UECPPBASICPROJECT_API AOneActor : public AActor

  7. {

  8. GENERATED_BODY()


  9. public:

  10. // Sets default values for this actor's properties

  11. AOneActor();

  12. UPROPERTY(VisibleAnywhere, Category = "One Actor Components")

  13. class UStaticMeshComponent* OneStaticMesh; // 网格模型


  14. ... // 略掉上边相关位置设置代码


  15. // 力

  16. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  17. FVector InitForce;

  18. // 力矩

  19. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  20. FVector InitTorque;


  21. // 是否忽略质量?

  22. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  23. bool bAccelChange;


  24. protected:

  25. // Called when the game starts or when spawned

  26. virtual void BeginPlay() override;


  27. public:

  28. // Called every frame

  29. virtual void Tick(float DeltaTime) override;


  30. };


  1. #include "OneActor.h"

  2. // 添加 UStaticMeshComponent 头文件

  3. #include "Components/StaticMeshComponent.h"


  4. // Sets default values

  5. AOneActor::AOneActor()

  6. {

  7. // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.

  8. PrimaryActorTick.bCanEverTick = true;


  9. OneStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OneStaticMesh"));


  10. // 物理

  11. InitForce = FVector(0.0f);

  12. InitTorque = FVector(0.0f);

  13. bAccelChange = false;

  14. }


  15. // Called when the game starts or when spawned

  16. void AOneActor::BeginPlay()

  17. {

  18. Super::BeginPlay();


  19. // 给予力 可以使物体运动, bAccelChange 视为忽视质量,这样 InitForce 不用给的特别大

  20. OneStaticMesh->AddForce(InitForce, "NAME_None", bAccelChange);

  21. // 给予力矩 可以使物体旋转

  22. OneStaticMesh->AddTorque(InitTorque, "NAME_None", bAccelChange);

  23. }


  24. // Called every frame

  25. void AOneActor::Tick(float DeltaTime)

  26. {

  27. Super::Tick(DeltaTime);

  28. }


  • 我们给多边形模型一个2000的力和100的力矩。多边形受力和力矩的影响,缓慢向-y轴移动,我们可以用角色去撞击多边形,让其有更大的力。



BP_OneActor 的碰撞扩展

  • 在场景中在创建一个 BP_OneActor蓝图 让场景中同时有两个 BP_OneActor蓝图实例,并且赋予不同颜色的材质。我们试图做一下,让两个多边形同时延-y轴运动,当两个多边形同时碰撞到墙面时,红色的多边形穿越墙面,而蓝色的因碰撞停留在墙上。


  • 关闭两个多边形的物理检测,并且去掉力、力矩代码。让多边形通过Tick代码改变位置。


  1. #pragma once


  2. #include "CoreMinimal.h"

  3. #include "GameFramework/Actor.h"

  4. #include "OneActor.generated.h"


  5. UCLASS()

  6. class UECPPBASICPROJECT_API AOneActor : public AActor

  7. {

  8. GENERATED_BODY()


  9. public:

  10. // Sets default values for this actor's properties

  11. AOneActor();


  12. // EditAnywhere:在资源和实例的属性窗口都可以编辑。与Visible*标识符冲突。

  13. UPROPERTY(VisibleAnywhere, Category = "One Actor Components")

  14. class UStaticMeshComponent* OneStaticMesh; // 网格模型


  15. // EditInstanceOnly:只能在实例的属性窗口编辑。与Visible*标识符冲突。

  16. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Vector")

  17. FVector InitLocation; // 游戏开始时 初始化位置


  18. // VisibleDefaultsOnly:在实例的属性窗口可视,但不可编辑。与Edit*冲突。

  19. UPROPERTY(VisibleInstanceOnly, Category = "One Actor Properties | Vector")

  20. FVector PlacedLocation; // UE4 编辑器中 放置的位置


  21. // EditDefaultsOnly:只能在资源的属性窗口编辑。与Visible*标识符冲突。

  22. UPROPERTY(EditDefaultsOnly, Category = "One Actor Properties | Vector")

  23. bool bGotoInitLocation; // 是否 编辑器放置的位置 移动到 初始位置


  24. // VisibleDefaultsOnly:在资源的属性窗口可视,但不可编辑。与Edit*冲突。

  25. UPROPERTY(VisibleDefaultsOnly, Category = "One Actor Properties | Vector")

  26. FVector WorldOrigin; // 世界原地坐标


  27. // ClampMin、 ClampMax 设置 TickLocoationOffset 的大小范围。

  28. // UIMin、 UIMax 在UI中体现出 大小范围。

  29. UPROPERTY(EditAnywhere, Category = "One Actor Properties | Vector", meta=(ClampMin=-50.0f, ClampMax=50.0f, UIMin=-50.0f, UIMax=50.0f))

  30. FVector TickLocationOffset; // Tick时 移动位置偏移大小。


  31. UPROPERTY(EditAnywhere, Category = "One Actor Properties | Vector")

  32. bool bCanTickMove; // 是否在Tick中移动


  33. /*

  34. // 力

  35. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  36. FVector InitForce;

  37. // 力矩

  38. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  39. FVector InitTorque;


  40. // 是否忽略质量?

  41. UPROPERTY(EditInstanceOnly, Category = "One Actor Properties | Physics")

  42. bool bAccelChange;

  43. */

  44. protected:

  45. // Called when the game starts or when spawned

  46. virtual void BeginPlay() override;


  47. public:

  48. // Called every frame

  49. virtual void Tick(float DeltaTime) override;


  50. };


  1. #include "OneActor.h"

  2. // 添加 UStaticMeshComponent 头文件

  3. #include "Components/StaticMeshComponent.h"


  4. // Sets default values

  5. AOneActor::AOneActor()

  6. {

  7. // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.

  8. PrimaryActorTick.bCanEverTick = true;


  9. OneStaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("OneStaticMesh"));

  10. InitLocation = FVector(0.0f);

  11. PlacedLocation = FVector(0.0f);

  12. bGotoInitLocation = false;

  13. WorldOrigin = FVector(0.0f);

  14. TickLocationOffset = FVector(0.0f);

  15. bCanTickMove = true;


  16. // 物理

  17. //InitForce = FVector(0.0f);

  18. //InitTorque = FVector(0.0f);

  19. //bAccelChange = false;

  20. }


  21. // Called when the game starts or when spawned

  22. void AOneActor::BeginPlay()

  23. {

  24. Super::BeginPlay();


  25. PlacedLocation = GetActorLocation();

  26. if (bGotoInitLocation)

  27. {

  28. SetActorLocation(InitLocation);

  29. }


  30. // 给予力 可以使物体运动, bAccelChange 视为忽视质量,这样 InitForce 不用给的特别大

  31. //OneStaticMesh->AddForce(InitForce, "NAME_None", bAccelChange);

  32. // 给予力矩 可以使物体旋转

  33. //OneStaticMesh->AddTorque(InitTorque, "NAME_None", bAccelChange);

  34. }


  35. // Called every frame

  36. void AOneActor::Tick(float DeltaTime)

  37. {

  38. Super::Tick(DeltaTime);


  39. if (bCanTickMove)

  40. {

  41. // 获取碰撞信息

  42. FHitResult HitResult;

  43. AddActorLocalOffset(TickLocationOffset * DeltaTime, true, &HitResult);

  44. }


  45. }


  • 修改红色多边形的碰撞规则,让其忽略 WorldStatic ,世界中静态物体,墙都是静态的。




文章转载自林元皓,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论