ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

探究如何实现AI集群

2022-04-12 02:01:57  阅读:232  来源: 互联网

标签:Box Distance FVector AI void Factory 探究 集群 Circle


第一种,自行实现

参考了一下一个unity项目的阵列实现。

https://github.com/Matthew-J-Spencer/Formations

第二种用商城提供的现成的工具

接下来是自己造轮子的时间了。

具体的并没有按这来写,实际的核心代码如下

TArray<FVector> FormationFactory::GetPoints(FVector orignPostion)
{
	switch (FormationType)
	{
	case EFormationType::Circle:return  GetCirclePoint(orignPostion);
		break;
	case EFormationType::Box:return GetBoxPoint(orignPostion);
		break;
	default:return TArray<FVector>();
		break;
	}
}

TArray<FVector> FormationFactory::GetBoxPoint(FVector orignPostion)
{
	TArray<FVector> pointArray(new FVector(),Box.Count);
	FVector fristVector;
	int32 width;
	int32 high;

	//get the first point , then use the point can get other points by calculation
	width = Box.width;
	high = FMath::CeilToInt(Box.Count/width) ;
	fristVector = FVector(orignPostion.X-(width/2)*Distance,orignPostion.Y+(high/2)*Distance,orignPostion.Z);
	for (int i=0;i<pointArray.Num();i++)
	{
		pointArray[i].X = fristVector.X + ((i)%width)*Distance;
		pointArray[i].Y = fristVector.Y - ((i)/width)*Distance;
		pointArray[i].Z = fristVector.Z;
	}
	return pointArray;
}

TArray<FVector> FormationFactory::GetCirclePoint(FVector orignPostion)
{
	TArray<FVector> pointArray(new FVector(),Circle.Count);
	FVector fristVector = orignPostion;
	int32 trunsNum = 0;
	int32 currntIndex = 0;
	int32 currntMaxIndex = 1;
	for (int i=0;i<pointArray.Num();i++)
	{
		/*//first
		pointArray[i] = fristVector;
		//second
		pointArray[i] = fristVector + FVector(0,100,0);
		//third
		pointArray[i] = fristVector + FVector(0,100,0).RotateAngleAxis(60*PI/180,FVector::UpVector);*/
		//normal
		currntIndex++;
		if(currntIndex>currntMaxIndex)
		{
			currntIndex = 1;
			currntMaxIndex += Circle.Raise;
			trunsNum++;
		}
		
		pointArray[i] = fristVector + FVector(0,1,0).RotateAngleAxis((float)(currntIndex-1)/currntMaxIndex*360,FVector::UpVector)*Distance*trunsNum;
		// UE_LOG(LogTemp,Log,TEXT("当前圈数:%d ,当前圈数中下标:%d,当前圈数最大下标:%d"),trunsNum,currntIndex,currntMaxIndex);
	}
	return pointArray;
}

IMPLEMENT_SIMPLE_AUTOMATION_TEST(FFormationFactoryTest,"Test.Formation Test",EAutomationTestFlags::EditorContext | EAutomationTestFlags::EngineFilter)

bool FFormationFactoryTest::RunTest(const FString& Parameters)
{
	FormationFactory formationFactory;
	formationFactory.Box = FBoxType(10,5);
	formationFactory.Circle = FCircleType(10,3);
	formationFactory.Distance = 100;
	formationFactory.FormationType = EFormationType::Box;

void AFormationCreate_Base::CreateBoxFormation(FBoxType Box)
{
	
	Factory.Box = Box;
	Factory.Distance = Distance;
	Factory.FormationType = EFormationType::Box;
	CreateAIs(Box.Count,Factory.GetPoints(GetTargetLocation()));
	
}

void AFormationCreate_Base::CreateCircleFormation(FCircleType Circle)
{
	Factory.Circle = Circle;
	Factory.Distance = Distance;
	Factory.FormationType = EFormationType::Circle;
	CreateAIs(Circle.Count,Factory.GetPoints(GetActorLocation()));
}

void AFormationCreate_Base::updataBox(FBoxType Box)
{
	if(AIs.Num() == 0)
	{
		CreateBoxFormation(Box);
		return;;
	}
	updataAICount(Box.Count);
	Factory.Box = Box;
	Factory.Distance = Distance;
	Factory.FormationType = EFormationType::Box;
	updataAis(Factory.GetPoints(GetActorLocation()));
}

void AFormationCreate_Base::updataCircle(FCircleType Circle)
{
	if(AIs.Num() == 0)
	{
		CreateCircleFormation(Circle);
		return;;
	}
	updataAICount(Circle.Count);
	Factory.Circle = Circle;
	Factory.Distance = Distance;
	Factory.FormationType = EFormationType::Circle;
	updataAis(Factory.GetPoints(GetActorLocation()));
}

void AFormationCreate_Base::updataAICount(uint32 Count)
{
	int32 tempCount = Count;
	if((this->AICount) == tempCount)
		return;
	if((this->AICount) > tempCount)
	{
		//make the other character be unactive
		for(int i = tempCount-1;i<AIs.Num();i++)
		{
			AIs[i]->SetHidden(true);
			AIs[i]->SetActorHiddenInGame(true);
		}
	}
	if((this->AICount) <tempCount)
	{
		//active some unactive character,and create some character if this characters is less
		int newAIs =  tempCount-AIs.Num();
		for(int i = 0;i<newAIs;i++)
		{
			CreateAI(FVector::ZeroVector);
		}
	}
	this->AICount = tempCount;
}

void AFormationCreate_Base::CreateAI(FVector item)
{
	DrawDebugBox(GetWorld(),item,FVector(5),FColor::Red,false,10,0,0);
	item += FVector(0,0,100);
	FRotator rotator = GetActorRotation();
	ACharacter* AICharacter = (ACharacter*)(GetWorld()->SpawnActor(AI,&item,&rotator)) ;
	if (IsValid(AICharacter))
	{
		AIs.Add(AICharacter);
		AICharacter->SetActorLocation(item);
		
		// AICharacter->PossessedBy(GetWorld()->SpawnActor<AAIController>(AI.GetDefaultObject()->AIControllerClass));
		UE_LOG(LogTemp,Log,TEXT("已生成"));
	}
	
}

void AFormationCreate_Base::CreateAIs(uint32 Count, const TArray<FVector>& list)
{
	
	for(FVector item:list)
	{
		CreateAI(item);
	}
	AICount = Count;
}

void AFormationCreate_Base::updataAis(const TArray<FVector>& list)
{
	UE_LOG(LogTemp,Log,TEXT("更新坐标"));
	for(int i = 0;i<AICount;i++)
	{
		//if it postion is defaluet,set new postion,if not then move to new postion
		if(AIs[i]->GetActorLocation() == FVector::ZeroVector)
		{
			AIs[i]->SetActorLocation(list[i]);
		}else
		{
			// AAIController* AIController = Cast<AAIController> (AIs[i]->GetController());
			// AIController->MoveTo(list[i]);
			AAIController* AICtl = AIs[i]->GetController<AAIController>();
			if(IsValid(AICtl))
			{
				FVector point = FVector(list[i]);
				AICtl->MoveToLocation(point,10,false);
			}
		}
	}
}
	UFUNCTION(BlueprintCallable,Category="Formation")
	void CreateBoxFormation(FBoxType Box);
	UFUNCTION(BlueprintCallable,Category="Formation")
	void CreateCircleFormation(FCircleType Circle);
	UFUNCTION(BlueprintCallable,Category="Formation")
	void updataBox(FBoxType Box);
	UFUNCTION(BlueprintCallable,Category="Formation")
	void updataCircle(FCircleType Circle);

上面是暴露给蓝图的函数,因为具体的阵列效果需要在蓝图里去检查。因此做了基本的暴露

大致思路是先算出来具体的坐标,再再对应坐标上生成AI,当更新阵列时,通过AI的位移方法移动到指定点上。

不足的地方

阵列变化不够自然:解决方法通过一定计算,给每个点匹配最佳的位移坐标

位移之后AI方向不受控制:在AI移动的方法添加方向的计算,以便于在最后的时间内,能够自然的转换到指定方向。

总而言之。需要提升的地方有很多,这里花了两天时间,学习到最后将效果展示出来。

标签:Box,Distance,FVector,AI,void,Factory,探究,集群,Circle
来源: https://www.cnblogs.com/ldnanchao/p/16133329.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有