首先把这一期的资源导入一下

创建一个球体类,继承于pawn类
为其添加静态组件
- UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "Components")
- class UStaticMeshComponent * MeshComponent;
-
- ==================================================================
- #include "Components/StaticMeshComponent.h"
-
- MeshComponent = CreateDefaultSubobject
(TEXT("MeshComponent")); - RootComponent = MeshComponent;
编译,为其创建蓝图类

为其组件设为一个球体
拖到场景中,发现太大了
我们为其创建一个小球网格体模型
首先创建一个文件夹
我们把这个小球网格体复制到我们这个文件夹下面

重命名一下这个网格体
进入这个网格体,修改一下比例
在类中换上这个网格体

shift+end让其紧贴地面
然后创建材质文件
先将材质设为白色
在网格体中赋予材质

把导航体拖入场景中
然后我们拉大体积,让其覆盖整个地面

然后让其嵌入到地板底下
按一下p,就可以显示导航的范围

我们可以看到,球体本身也会影响导航
小球mesh组件里面,去掉这个勾
我们为这个小球,写蓝图
然后为我们的小球随便添加一个移动组件

编译,测试,小球开局真的动了
现在我们将移动逻辑写的更复杂一点

将移动速度变小,发现小球一直在我们屁股后面追
====================================
我们继续提高逻辑,让其自动添加路径
首先自定义事件


测试,已经画出了路径点
在c++文件中加上这个

在小球头文件中,添加三个变量
- //移动速度
- UPROPERTY(EditDefaultsOnly, Category = "TracerBot")
- float MovementForce;
-
- //是否让移动速度改变
- UPROPERTY(EditDefaultsOnly, Category = "TracerBot")
- bool bUseVelocityChange;
-
- //移动到目标的阈值
- UPROPERTY(EditDefaultsOnly, Category = "TracerBot")
- float RequiredDistanceToTarget;
在构造函数中初始化这三个变量,并将mesh组件的模拟物理激活
- AASTrackerBot::AASTrackerBot()
- {
- // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
- PrimaryActorTick.bCanEverTick = true;
- MeshComponent = CreateDefaultSubobject
(TEXT("MeshComponent")); - MeshComponent->SetSimulatePhysics(true);
- RootComponent = MeshComponent;
-
- MovementForce = 1000;
- bUseVelocityChange = false;
- RequiredDistanceToTarget = 100;
- }
在小球的头文件中,添加寻找路径点的函数,和路径点变量
FVector GetNextPathPoint();
-
- //路径点
- FVector NextPathPoint;
- #include "Components/StaticMeshComponent.h"
- #include "GameFramework/Character.h"
- #include"Kismet/GamePlayStatics.h"
- #include "NavigationSystem.h"
- #include "NavigationPath.h"
- #include "DrawDebugHelpers.h"
定义这个函数
- FVector AASTrackerBot::GetNextPathPoint()
- {
- //得到0号玩家
- ACharacter *playerPawn = UGameplayStatics::GetPlayerCharacter(this, 0);
- //找到通往玩家的路径
- UNavigationPath *NavPath = UNavigationSystemV1::FindPathToActorSynchronously(this, GetActorLocation(), playerPawn);
- if (NavPath->PathPoints.Num() > 1)
- {
- //返回第二个点
- return NavPath->PathPoints[1];
- }
- else
- {
- return GetActorLocation();
- }
- }
在游戏开始函数中,调用这个函数
- void AASTrackerBot::BeginPlay()
- {
- Super::BeginPlay();
- NextPathPoint = GetNextPathPoint();
- }
在每帧函数里,不断得去移动
- void AASTrackerBot::Tick(float DeltaTime)
- {
- Super::Tick(DeltaTime);
- //得到小球自身与下一个点的距离
- float DistanceToTarget = (NextPathPoint - GetActorLocation()).Size();
- //如果大于阈值,就继续滚
- if (DistanceToTarget > RequiredDistanceToTarget)
- {
- //小球的移动方向
- FVector ForceDirection = NextPathPoint - GetActorLocation();
- ForceDirection.Normalize();
- //小球的推力
- ForceDirection *= MovementForce;
- MeshComponent->ComponentVelocity.Size();
- MeshComponent->AddImpulse(ForceDirection, NAME_None, bUseVelocityChange);
- DrawDebugDirectionalArrow(GetWorld(), GetActorLocation(), GetActorLocation() + ForceDirection, 32, FColor::Red, false, 0.0f, 0, 1.0f);
- }
- //如果到达了路径点,就生成下一个点,继续移动
- else
- {
- NextPathPoint = GetNextPathPoint();
- DrawDebugString(GetWorld(), GetActorLocation(), "Target Reached!");
- }
- //在下一个目标点画一个球
- DrawDebugSphere(GetWorld(), NextPathPoint, 20, 12, FColor::Yellow, false, 0.0f, 0, 1.0f);
-
- }
编译,然后在小球的mesh组件里面,勾上模拟物理

测试成功
