본문 바로가기

언리얼엔진/ThirdPersonTemplete

Widget 머리에 달기

userWidget을 부모로 Itemshop이라는 클라스를 만들자

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "MyUserWidget.h"
#include "ItemShop.generated.h"

/**
 * 
 */
UCLASS()
class TEAM_ISLAND_MASTER_API UItemShop : public UMyUserWidget
{
	GENERATED_BODY()

public : 
	UPROPERTY(EditAnyWhere, BlueprintReadWrite,Category = "Shop")
	class AMyTable* ownerTable;
	UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = "Shop")
	FText ctextId;
	UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category = "Shop")
	FText ctextPos;
	UFUNCTION( BlueprintCallable, Category = "Shop")
	void SetTextID(FText value);
	UFUNCTION(BlueprintCallable, Category = "Shop")
	void SetTextPosition(FText value);
	
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "ItemShop.h"

void UItemShop::SetTextID(FText value)
{
	ctextId = value;
}

void UItemShop::SetTextPosition(FText value)
{
	ctextPos = value;
}

 

텍스트를 윗젯클래스의 변수와 직접 연결 나중에 알은건데 이러면 NPC쪽에서 계속 업데이트를 해줘야해서 개선할 필요 있음.

위젯을달 NPC를 하나 만들자

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "NPC.generated.h"


UCLASS()
class TEAM_ISLAND_MASTER_API ANPC : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ANPC();
	UPROPERTY(EditDefaultsOnly, Category = FSM)
	float idleDelayTime = 2;
	// 경과시간
	float currentTime = 0;

	// 타겟
	UPROPERTY(VisibleAnywhere, Category = FSM)
	class AMyPlayer* target;

	// 소유액터
	UPROPERTY()
	class ANPC* me;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spawn)
	FString npcid;
	//이동속도
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spawn)
	float moveSpeed;
	UPROPERTY(EditAnywhere, Category = FSM)
	float attackRange = 150.0f;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = FSM)
	FVector destination;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = FSM)
	FVector dir;
	// 사용중인 애니메이션 블루프린트
	UPROPERTY()
	class UEnemyAnim* anim;

	UPROPERTY(EditAnywhere, Category = Animation)
	class UAnimMontage* damageAnim;

	UPROPERTY(EditAnywhere)
	TSubclassOf<class UItemShop> widgetRef;
	UPROPERTY()
	class UItemShop* hpBar;
	UPROPERTY()
	class UWidgetComponent* widgetComp;
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	UFUNCTION()
	void move(float DeltaTime);
	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

 

// Fill out your copyright notice in the Description page of Project Settings.
#include "NPC.h"
#include "EnemyFSM.h"
#include "MyPlayer.h"
#include "UnrealWidget.h"
#include "Animation/AnimMontage.h"
#include <Kismet/GameplayStatics.h>
#include <Kismet/KismetMathLibrary.h>
#include <Components/WidgetComponent.h>
#include <Components/CapsuleComponent.h>
#include "EnemyAnim.h"
#include "ItemShop.h"


// Sets default values
ANPC::ANPC()
{
 	// Set this character to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;
	ConstructorHelpers::FObjectFinder<USkeletalMesh> tempMesh(TEXT("/Game/BG/CityofBrass_Enemies/Meshes/Enemy/Archer/Archer.Archer"));
	// 1-1. 데이터 로드 성공하면
	if (tempMesh.Succeeded())
	{
		UE_LOG(LogTemp, Warning, TEXT("Enemy Skeletal Mesh Loading"));
		// 1-2. 데이터 할당
		GetMesh()->SetSkeletalMesh(tempMesh.Object);
		// 1-3. 메쉬 위치 및 회전 설정
		GetMesh()->SetRelativeLocationAndRotation(FVector(0, 0, -88), FRotator(0, 0, 0));
		// 1-4. 메쉬 크기 수정
		GetMesh()->SetRelativeScale3D(FVector(0.84f));
	}


	widgetComp = CreateDefaultSubobject<UWidgetComponent>(TEXT("HPWidget"));
	widgetComp->SetupAttachment(GetMesh());
	widgetComp->SetRelativeLocation(FVector(0, 0, 300.0f));

	UClass* WidgetCompClass = LoadClass<UUserWidget>(NULL, TEXT("/Game/UI/WBP_HPBarTest.WBP_HPBarTest_C"));
	if (WidgetCompClass) {
		widgetComp->SetWidgetClass(WidgetCompClass);
		widgetComp->SetWidgetSpace(EWidgetSpace::World);
	}
	moveSpeed = 1.f;
}

// Called when the game starts or when spawned
void ANPC::BeginPlay()
{
	Super::BeginPlay();

	auto actor = UGameplayStatics::GetActorOfClass(GetWorld(), AMyPlayer::StaticClass());
	// ATPSPlayer 타입으로 캐스팅
	target = Cast<AMyPlayer>(actor);
	// 소유객체 가져오기
	//me = Cast<ANPC>(GetOwner());
	me = this;
	widgetComp->InitWidget();

	hpBar = Cast<UItemShop>(widgetComp->GetUserWidgetObject());
	if (IsValid(hpBar)) {
		//FText idText = FText::FromString(FString::FromInt(12));
		FVector _pos = target->GetActorLocation();
		hpBar->ctextId = GetClass()->GetDisplayNameText();
		hpBar->ctextPos = FText::FromString(FString::Printf(TEXT("%f %f %f"), _pos.X, _pos.Y, _pos.Z));
	}

}

// Called every frame
void ANPC::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	 //1.타겟 목적지가 필요하다.
	move(DeltaTime);
}

void ANPC::move(float DeltaTime)
{
	destination = target->GetActorLocation();
	// 2.방향이 필요하다.
	dir = destination - GetActorLocation();

	// 3.방향으로 이동하고 싶다.
	moveSpeed = 10;
	float _speed = DeltaTime * moveSpeed;

	FRotator _dirRot = UKismetMathLibrary::FindLookAtRotation(GetActorLocation(), target->GetActorLocation());

	SetActorRotation(FRotator(0, _dirRot.Yaw, 0));
	////dir = FVector(dir.X, dir.Y, 0).GetSafeNormal();
	////float _speed = dir.Length() * moveSpeed * 0.1;
	double _distance = dir.Length();
	if (_distance > 150.f) {
		AddMovementInput(me->GetActorForwardVector() * _speed); //* _speed
	}


	if (IsValid(hpBar)) {
		hpBar->ctextId = GetClass()->GetDisplayNameText();
		hpBar->ctextPos = FText::FromString(FString::Printf(TEXT("%d"), (int) _distance));
	}
}

// Called to bind functionality to input
void ANPC::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

스포너를 하나 만들자;

웃긴건 스폰한 캐릭터가 움직이지 않는다 결국 알아낸건데 default pawn character를 연결해줘야하는데 아직 c++클래스를 찾지 못했다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "NPCSpawner.generated.h"

UCLASS()
class TEAM_ISLAND_MASTER_API ANPCSpawner : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	ANPCSpawner();
	void SpawnEnemy(int id);
protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;
	UPROPERTY(EditAnywhere, Category = Spawn)
	class UArrowComponent* spawnPoint;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spawn)
	float minDelay = 5.f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spawn)
	float maxDelay = 10.f;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Time)
	float delayTime = 5.f;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Spawn)
	TArray<TSubclassOf<class ANPC>> enemyClass;
private:
	float currentTime = 0;
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "NPCSpawner.h"
#include "Components/ArrowComponent.h"
#include "NPC.h"
// Sets default values
ANPCSpawner::ANPCSpawner()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	spawnPoint = CreateDefaultSubobject<UArrowComponent>(TEXT("Spawn Pointer"));
	spawnPoint->SetRelativeLocation(FVector(0, 0, 100));
	spawnPoint->SetRelativeRotation(FRotator(0, -90, 0));
	//spawnPoint->SetupAttachment(RootComponent);
}

void ANPCSpawner::SpawnEnemy(int id)
{
	if (enemyClass.Num() > 0) {
		FActorSpawnParameters Param;
		Param.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
		auto _actor = GetWorld()->SpawnActor<ANPC>(enemyClass[0], spawnPoint->GetComponentLocation(), 
			spawnPoint->GetComponentRotation(), Param);
		//GetWorld()->AddController();
	}
	
}

// Called when the game starts or when spawned
void ANPCSpawner::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void ANPCSpawner::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	currentTime += DeltaTime;
	if (currentTime > delayTime) {
		int _id = FMath::RandRange(0, enemyClass.Num() - 1);
		SpawnEnemy(_id);
		currentTime = 0;
	}

}

'언리얼엔진 > ThirdPersonTemplete' 카테고리의 다른 글

캐릭터만들기 정리  (0) 2023.12.04
스폰한 캐릭터 안움직이는 이유  (0) 2023.12.04
AnimNotify  (0) 2023.11.16
언리얼 Animation Montage  (0) 2023.11.14
캐릭터 메시 지정하기  (0) 2023.11.13