Path Guide - B477042/GraduationProject GitHub Wiki

About Path Guide


Player์˜ ๊ฒŒ์ž„ ์ง„ํ–‰์— ๋„์›€์ด ๋˜๋„๋ก ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„

Node๋“ค์„ Treeํ˜•ํƒœ๋กœ ๊ตฌ์„ฑํ•œ ํ›„, ๊ทธ ์†์—์„œ Astar๋ฅผ ์ ์šฉํ•œ๋‹ค๋ฉด ๊ธธ์„ ์•ˆ๋‚ดํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ถ๊ธˆํ•ด์„œ Tree์™€ Astar๋ฅผ ์กฐํ•ฉํ•œ ํ˜•ํƒœ๋ฅผ ๋„๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

AstarFinder.h

UCLASS()
class ESCAPEGAME_API AAStarFinder : public AActor
{
//๋ฐฉ๋ฌธํ•ด์•ผ๋  ๋…ธ๋“œ
	//UPROPERTY(Transient)
	TQueue<TWeakObjectPtr<AAstarNode>>ToVisitNodes;

	//Goal Node in map
	UPROPERTY(Transient, EditInstanceOnly, meta = (AllowPrivateAccess = "true"))
	TWeakObjectPtr<AAstarNode> GoalNode;

	//CardKey Node
	TWeakObjectPtr<AAstarNode>KeyNode;
	
	UPROPERTY(Transient, meta = (DisplayName = "Nodes"))
		TArray< TWeakObjectPtr<AAstarNode>>AllNodes;
}

์ดˆ๊ธฐ์—” UE4์˜ Singleton class๋กœ ์„ค์ •ํ•ด์„œ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ, Singleton class์˜ ํŠน์„ฑ์ƒ ๊ณ„์† ์—๋””ํ„ฐ์™€ ๊ฒŒ์ž„์— ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ชฉ์ ์— ๋งž์ง€ ์•Š์•„์„œ Actor ํ˜•ํƒœ๋กœ ๋‹ค์‹œ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.
AAstarNode๋“ค์„ AllNodes๋ผ๋Š” ๋ฐฐ์—ด์— Weak Pointer ํ˜•ํƒœ๋กœ ๋‹ด์•„๋’€์Šต๋‹ˆ๋‹ค.
๊ฒฝ๋กœ๋ฅผ ์ฐพ์€ ๋…ธ๋“œ๋ฅผ Goal ํ˜น์€ Key ๋ฉค๋ฒ„ ๋ณ€์ˆ˜ ๊ฐ’์œผ๋กœ ์ง€์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.

AstarFinder.cpp

void AAStarFinder::PathFind(AAstarNode * Start,EPathTarget Mode)
{
	if (!Start)
	{
		EGLOG(Error, TEXT("Start is nullptr"));
		return;
	}

	ToVisitNodes.Empty();
	ToVisitNodes.Enqueue(Start);
		switch (Mode)
		{
		case EPathTarget::Key:
			KeyFind(Start, KeyNode.Get());
			break;
		case EPathTarget::Gate:
			GoalFind(Start, GoalNode.Get());
			break;
		default:
			break;
		}


}

void AAStarFinder::GoalFind(AAstarNode * Start, AAstarNode * Goal)
{

if (!Start)
	{
		EGLOG(Error, TEXT("Nullptr"));
		return;
	}
	if (!Goal)
	{
		EGLOG(Error, TEXT("Nullptr"));
		return;
	}




๊ฒฝ๋กœ์˜ ํƒ์ƒ‰ ๊ธฐ๋Šฅ์œผ๋กœ Goal๊ณผ Key๋ฅผ ์ฐพ๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‘˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ™๊ณ  ์ฐพ๋Š” ๋Œ€์ƒ๋งŒ ๋‹ค๋ฅธ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
	TWeakObjectPtr<AAstarNode> PopedNode;
	int i = 0;


	//๋ฐฉ๋ฌธํ•ด์•ผ๋  ๋…ธ๋“œ๊ฐ€ ๋น„์›Œ์งˆ ๋•Œ๊นŒ์ง€
	while (!ToVisitNodes.IsEmpty())
	{
	
		i++;

		//Queue์—์„œ ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ธ๋‹ค
		ToVisitNodes.Dequeue(PopedNode);

		if (!PopedNode.IsValid())
		{
			EGLOG(Error, TEXT("PopedNode is invalid"));
			return;
		}

		//EGLOG(Warning, TEXT("Current Node : %s"), *PopedNode->GetName());
		//๋…ธ๋“œ์˜ ๋ฐฉ๋ฌธ์„ ๋งˆ์นœ๋‹ค
		PopedNode->VisitNode();

		//๊บผ๋‚ธ ๋…ธ๋“œ๊ฐ€ Goal๊ณผ ์œ„์น˜๊ฐ€ ๊ฐ™๋‹ค๋ฉด 
		if (PopedNode->GetActorLocation() == Goal->GetActorLocation())
		{
			//GoalNode๋ฅผ ์„ค์ •ํ•ด์ฃผ๊ณ  ToVisiteNode๋ฅผ ๋น„์›Œ์ค€๋‹ค
		//	EGLOG(Error, TEXT("Goal Find! : %s"), *PopedNode->GetName());
			GoalNode = PopedNode.Get();
			ToVisitNodes.Empty();
			break;
		}

while ๋ฃจํ”„์˜ ์กฐ๊ฑด์œผ๋กœ ToVisitNodes๊ฐ€ ๋น„์›Œ์งˆ ๋•Œ๊นŒ์ง€ ๋ฐ˜๋ณต๋˜๊ฒŒ ํ–ˆ์Šต๋‹ˆ๋‹ค.๊ทธ๋ฆฌ๊ณ  Queue์— ๋‹ด๊ธด ์ˆœ์„œ๋Œ€๋กœ ๋…ธ๋“œ๋“ค์„ ๊ฒ€์‚ฌํ–ˆ์Šต๋‹ˆ๋‹ค.
๋…ธ๋“œ๋ฅผ ๊บผ๋‚ธ ์งํ›„ ๋…ธ๋“œ์— ๋ฐฉ๋ฌธํ•œ ๋…ธ๋“œ์ž„์„ ํ‘œ์‹œํ–ˆ์Šต๋‹ˆ๋‹ค. Goal ๋…ธ๋“œ๋ฅผ ์ฐพ๋Š” ์ž‘์—…์ด๊ธฐ์— ์—ฌ๊ธฐ์„œ๋Š” Goal ๋…ธ๋“œ์ธ์ง€ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
		//์ธ๊ทผ๋…ธ๋“œ๋“ค์˜ ์ฃผ๋ณ€ ๋…ธ๋“œ๋“ค์ด ์žˆ๋‹ค๋ฉด
		if (PopedNode->NearNodes.GetData() != nullptr)
			//์ธ๊ทผ ๋…ธ๋“œ๋“ค์˜ ๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค
		{
			for (auto it : PopedNode->NearNodes)
			{
				//์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด ๋„˜์–ด๊ฐ„๋‹ค
				if (!it.IsValid())continue;
				//๋ฐฉ๋ฌธํ–ˆ๋˜ ๋…ธ๋“œ๋ฉด ๋„˜์–ด๊ฐ„๋‹ค.
				if (it->IsVisitedNode())continue;

				it->CalcFCount(Start->GetActorLocation(), Goal->GetActorLocation());
				
			
			}

			//๊บผ๋‚ธ ๋…ธ๋“œ์˜ ์ฃผ๋ณ€ ๋…ธ๋“œ๋“ค์˜ ์ด์ „ ๋…ธ๋“œ๋ฅผ ๊บผ๋‚ธ ๋…ธ๋“œ๋กœ ์„ค์ •ํ•ด์ค€๋‹ค. 
			PopedNode->SetNearNodesPrevAsMe();
					
		
			//fcount ์ˆœ์œผ๋กœ ์ •๋ ฌ
			for (int k = 0; k < PopedNode->NearNodes.Num();++k)
			{
				for (int j = k+1 ; j < PopedNode->NearNodes.Num()-1; ++j)
				{
					//๋น„๊ต์ „ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
					if (!PopedNode->NearNodes[k].IsValid() || !PopedNode->NearNodes[j].IsValid())continue;
					if (PopedNode->NearNodes[k]->GetF() > PopedNode->NearNodes[j]->GetF())
						PopedNode->NearNodes.Swap(k, j);
				}

			}

๋ฐฉ๋ฌธํ•œ ์ด ๋…ธ๋“œ๊ฐ€ Goal์ด ์•„๋‹ˆ๋ผ๋ฉด ์ธ๊ทผ ๋…ธ๋“œ๋“ค์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•œ ํ›„ F Count๋ฅผ ๊ณ„์‚ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
๊ฒ€์‚ฌ๊ฐ€ ๋๋‚œ ํ›„, ๊ฒฝ๋กœ๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ List ํ˜•ํƒœ๋กœ Node๋“ค์„ ์—ฐ๊ฒฐ ์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ๋ณ€ ๋…ธ๋“œ๋“ค์˜ ์ด์ „ ๋…ธ๋“œ ๊ฐ’์œผ๋กœ ์ž์‹ ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  Near Node๋“ค์˜ ๋ฐฐ์—ด ์ˆœ์„œ๋ฅผ Fcount์ˆœ์œผ๋กœ ๋‹ค์‹œ ์ •๋ ฌ์„ ํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ์šฐ์˜ ์ˆ˜๊ฐ€ ๋งŽ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— Bubble Sort๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
F,G,H ์นด์šดํŠธ์˜ ๊ณ„์‚ฐ์˜ ๊ธฐ์ค€์€ ๊ฐ์ฒด์˜ ์ขŒํ‘œ ๋ฒกํ„ฐ ๊ฐ’์œผ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค.

			
			//์ •๋ ฌ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋„ฃ๋Š”๋‹ค
			for (auto it : PopedNode->NearNodes)
			{
				
				//์œ ํšจํ•˜์ง€ ์•Š๋‹ค๋ฉด ๋„˜์–ด๊ฐ„๋‹ค
				if (!it.IsValid())continue;

				//๋ฐฉ๋ฌธํ–ˆ๋˜ ๋…ธ๋“œ๋ฉด ๋‹ค์‹œ ์•ˆ ๋„ฃ์–ด๋„ ๋œ๋‹ค
				if (it->IsVisitedNode())continue;
				//PopedNode->VisitNode();
			//	EGLOG(Warning, TEXT("Enqueue : %s"), *it->GetName());
				ToVisitNodes.Enqueue(it.Get());


			}

		

		}
	}
    //================ While ๋ฃจํ”„ ์ข…๋ฃŒ ==============

	//๊ณจ ๋…ธ๋“œ๋ฅผ ์ฐพ์•˜๋‹ค๋ฉด ๊ฒฝ๋กœ๋“ค์„ ํ™œ์„ฑํ™” ์‹œ์ผœ์ค€๋‹ค
	if (GoalNode.IsValid())
		ShowPath(EPathTarget::Gate);
}

์ •๋ ฌ๋œ ์ˆœ์„œ๋Œ€๋กœ ToVisitNodes์— ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.
While ๋ฃจํ”„๊ฐ€ ๋๋‚˜๊ณ  Goal Node๋ฅผ ๋ฐœ๊ฒฌํ•ด์„œ ์ฐพ์•˜๋‹ค๋ฉด, Node์— ์ง€์ •ํ•œ ์ด์ „ ๋…ธ๋“œ๋“ค์„ ํ™œ์„ฑํ™” ์‹œ์ผœ ๊ฒฝ๋กœ๋ฅผ ํ‘œ์‹œํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

๊ตฌํ˜„์‹œ ์ง‘์ค‘ํ•œ ์ 

ํŠธ๋ฆฌ ํ˜•ํƒœ์˜ ๊ตฌ์กฐ์ธ๋ฐ Astar๊ฐ€ ๊ณผ์—ฐ ์ ์šฉ์ด ๋ ๊นŒํ•˜๋Š” ์˜๋ฌธ์ด ์žˆ์—ˆ์ง€๋งŒ ๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ฒฝ๋กœ๋Š” ์ž˜ ํ‘œ์‹œ๊ฐ€ ๋์Šต๋‹ˆ๋‹ค.
์ด ๊ฒƒ์„ ๊ตฌํ˜„ํ•  ๋•Œ ์ง‘์ค‘ํ•œ ์ ์€ ๊ณ„์‚ฐ์„ ์‹œ์ž‘ํ•˜๋Š” ์‹œ์ ์ด Player๊ฐ€ ๋…ธ๋“œ์— ๋‹ฟ์•˜์„ ๋•Œ ์‹œ์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ์ž‘์—… ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ด ๋ˆˆ์— ๋„๊ฒŒ ๋–จ์–ด์ง€๋Š” ๊ฒฝ์šฐ๋Š” ์—†์–ด์•ผ ๋œ๋‹ค๋Š” ์ƒ๊ฐ ๋ฟ์ด์˜€์Šต๋‹ˆ๋‹ค. ๋ˆˆ์— ๋„๋Š” ํ”„๋ ˆ์ž„ ๋ณ€ํ™” ์—†์ด ๊ฒฝ๋กœ๊ฐ€ ์ž˜ ํ‘œ์‹œ ๋˜์„œ ์ข‹์•˜์Šต๋‹ˆ๋‹ค.

๊ตฌํ˜„์‹œ ์–ด๋ ค์šด ์ 

AStar ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ •ํ™•ํžˆ ์ดํ•ดํ•˜๊ณ  ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด AStar๋ฅผ ๊ณต๋ถ€ํ•˜๋Š” ๊ณผ์ •์ด ์–ด๋ ค์› ์Šต๋‹ˆ๋‹ค. F,G,H๋ผ๋Š” ์•ŒํŒŒ๋ฒณ์„ ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•œ ํƒ“์— ์ด๊ฒŒ ๋ฌด์Šจ ์˜๋ฏธ์ธ์ง€ ํ–‡๊ฐˆ๋ ธ์Šต๋‹ˆ๋‹ค. ๊ณต๋ถ€๋ฅผ ๋๋‚ด๊ณ  ๋‚œ ๋’ค F,G,H์— ๊ฐ๊ฐ ์ด๋ฆ„์„ ์ƒˆ๋กœ ๋ถ™์ผ์ง€ ๊ณ ๋ฏผ์„ ํ–ˆ์ง€๋งŒ, ์ „ ์„ธ๊ณ„ ์‚ฌ๋žŒ๋“ค์ด F,G,H๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํฌ๊ธฐํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ์ž‘์—…์„ ํ†ตํ•ด ๊ฒŒ์ž„ ์†์— ๊ธธ ์ฐพ๊ธฐ๋ฅผ ์ ์šฉ ์‹œ์ผœ๋ณด๋Š” ๊ฒฝํ—˜์„ ํ•˜๊ฒŒ ๋๊ณ  ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์—†์—ˆ๋”๋ผ๋ฉด ์ด๊ฑธ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„ ํ–ˆ์„์ง€ ๋ง‰๋ง‰ํ•˜๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ค์–ด ์ด๋Ÿฐ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋งŒ๋“ค์–ด์ฃผ์‹  ๋ถ„๋“ค๊ป˜ ๊ฐ์‚ฌํ•œ ๋งˆ์Œ์„ ๊ฐ€์ง€๊ฒŒ ๋์Šต๋‹ˆ๋‹ค.

์ด ๋ฐฉ๋ฒ•์˜ ๋‹จ์ 

์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ, ๋…ธ๋“œ๋“ค์„ ์—๋””ํ„ฐ์—์„œ ์ด์–ด ๋ถ™์—ฌ์ฃผ๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ข‹์€ ์ž‘์—…์€ ์•„๋‹™๋‹ˆ๋‹ค. ์–ด๋–ป๊ฒŒํ•˜๋ฉด ์ž๋™์œผ๋กœ ์„œ๋กœ ๋ถ™์ผ ์ˆ˜ ์žˆ์„์ง€ ๋ฐฉ๋ฒ•์„ ์ฐพ๊ณ  ์‹ถ์–ด์กŒ์Šต๋‹ˆ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ