Ue4C++编程------血条与c++(一)

    前面的篇章中,我们介绍了AI,在该文中,我们将介绍血条。相信大家也玩过不少游戏,我本人还是很喜欢玩lol的,那么在一般的游戏中,敌人的头上,或者小兵的头顶上都会有一个血条,用来实时的显示小兵的目前血量,接下来我就来解析如实现,首先,在AI文件夹中,新建一个UserInterface,并命名为RobotHealth,如下所示:

    

    然后按照前面的UMG与c++文中的介绍,创建一个血条。两个文本,表示最大血量和当前血量,如下图所示:

    

    注意选择size为custom,即自定义的size。接下来则创建类,然后使这个ui的父类改为刚才创建的UserInterface类,这些都在前文中讲过,这里就不再赘述。在新建的userinterface类中,创建一个成员函数,UpdateHealth来更新我们的控件,如下所示:

UCLASS()
class BLOGPROJECT_API URobotHealthUserWidget : public UUserWidget
{
	GENERATED_BODY()

	UPROPERTY(meta = (BindWidget))
	class UTextBlock* CurrentHealth;

	UPROPERTY(meta = (BindWidget))
	class UTextBlock* MaxHealth;

	UPROPERTY(meta = (BindWidget))
	class UProgressBar* HealthPro;
	
public:
	void UpdateHealth(float CurrentHealth, float MaxHealth);
	
};

      实现:

void URobotHealthUserWidget::UpdateHealth(float CurrentHealth, float MaxHealth)
{
	if (this->CurrentHealth != nullptr)
	{
		FText text = FText::AsNumber(CurrentHealth);
		this->CurrentHealth->SetText(text);
	}

	if (this->MaxHealth != nullptr)
	{
		FText text = FText::AsNumber(MaxHealth);
		this->MaxHealth->SetText(text);
	}

	if (this->HealthPro != nullptr)
	{
		this->HealthPro->SetPercent(CurrentHealth / MaxHealth);
	}

}

接着在AI类中,创建一些WidgetComponnet成员,和一些血量成员,如下所示:

	UPROPERTY(EditAnywhere, Category = HealthUI)
	class UWidgetComponent* HealthUICompo;

	TSubclassOf<UUserWidget> HealthUIWidget;

	float CurrentHealth;
	float MaxHealth;

    在构造函数中,创建相关widget,并在beginplay中,设置相关资源,如下所示:

	HealthUICompo = CreateDefaultSubobject<UWidgetComponent>(TEXT("HealthUICompo"));
	static ConstructorHelpers::FClassFinder<UUserWidget> HealthUIBP(TEXT("/Game/ThirdPersonCPP/AI/RobotHealth"));
	if (HealthUIBP.Succeeded())
	{
		HealthUIWidget = HealthUIBP.Class;
	}
        if (HealthUICompo != nullptr)
	{
		HealthUICompo->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform); // 注意要attach,不然不会显示
	}

	CurrentHealth = 100.0f;
	MaxHealth = 100.0f;
    beginplay函数:
void AAIBlogCharacter::BeginPlay()
{
	Super::BeginPlay();
	
	if (Sight != nullptr)
	{
		Sight->OnSeePawn.AddDynamic(this, &AAIBlogCharacter::HaveSeePawn);
	}

	if (HealthUIWidget != nullptr)
	{
		URobotHealthUserWidget* Widget = CreateWidget<URobotHealthUserWidget>(GetWorld()->GetGameInstance(), HealthUIWidget);
		if (Widget != nullptr)
		{
			if (HealthUICompo != nullptr)
			{
				HealthUICompo->SetWidget(Widget);
			}
		}
	}

}

    在tick函数中,更新我们的血量信息,如下所示:

void AAIBlogCharacter::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	
	if (HealthUICompo != nullptr)
	{
		URobotHealthUserWidget* Widget = Cast<URobotHealthUserWidget>(HealthUICompo->GetUserWidgetObject());
		if (Widget != nullptr)
		{
			Widget->UpdateHealth(CurrentHealth, MaxHealth);
		}
	}
}
    接下来,打开我们的编辑器,然后编辑component,调整大小。为了测试并调整位置,我们预置widgetclass为蓝图创建的。调好位置后,应该设置为none,如下图所示。
    

    启动游戏,发现成功,如下图所示:

    

    但是,你会发现当你走到AI的后面的时候,血条不见了,原因是因为血条没有跟着视角旋转。因此,需要在Tick函数中,旋转我们的血条,如下所示:

	//旋转血条
	if (HealthUICompo != nullptr)
	{
		//首先得到我们的摄像机视角
		FVector PlayerLocation = GetWorld()->GetFirstPlayerController()->PlayerCameraManager->GetCameraLocation();
		//再得到我们的component的世界坐标
		FVector CompoLocation = HealthUICompo->GetComponentLocation();
		//使用一个数学函数,
		FRotator Turn = UKismetMathLibrary::FindLookAtRotation(CompoLocation, PlayerLocation);
		FRotator NewRotation(0, 0, 0);
		NewRotation.Yaw = Turn.Yaw; // 只旋转Yaw
		HealthUICompo->SetWorldRotation(NewRotation);
	}

    测试成功,可以看到,此时我们在人物的后面,血条也跟着我们旋转了。如下图所示:

    

    

猜你喜欢

转载自blog.csdn.net/li2818/article/details/80903692
今日推荐