Is there no way to set a pawn's team id for the new AI perception stuff to work

So I have an AI setup with the perception stuff and I can set if the AI will recognize enemies, but I can figure out how to set pawns on a team. Looking into it, the AISense_Sight::RegisterTarget will get a new actor and use GetTeamIdentifier to get the team ID, but the only class the implements the IGenericTeamAgentInterface is the AI controller meaning that player controllers are put on “noteam”.

Also, there is no way, that I can see, to set the team in data for a pawn. I’m not sure how ideal setup is supposed to be. I can go and implement that interface on our player controller. And how should we expose this to the editor? Should I just expose the teamID on the AI controller via UPROP?

I guess I’m wondering how you guys envision this to work and I’ll implement it on my side.


1 Like

Hey Troy,

Being able to use FGenericTeamId in Blueprints is still a missing feature.

The intended use is to have your classes implement the IGenericTeamAgentInterface and override the functions you need. Your GetGenericTeamId would return whatever you expose to the editor as UPROPERTY. Usually it’s a game-specific enum, that GetGenericTeamId can convert to FGenericTeamId.

Hope it makes sense.



1 Like

Ah ok, I saw that we can make enums (using them for a bt service actually). Ok, Ill expose that stuff. Thanks.

So the auto register as source is something that only works for pawns, which is fine. This makes sense actually. But the AIController is the only class in the code base that implementents IGenericTeamAgentInterface. So I’m confused on how this actually works. Do you guys have this working on your own internal pawns?

Another thing I found is that you can still put this on any actor, you just need to add the UAIPerceptionStimuliSourceComponent. This is very straight forward, but it doesn’t work. Looking into it, it look like ::OnRegister() deletes anything in RegisterAsSourceForSenses that is not null.

RegisterAsSourceForSenses.RemoveAllSwap([](TSubclassOf SenseClass){
		return SenseClass != nullptr;

I’m assuming this is a typo and you mean to clean our null references. I’ve changed it locally and it seems to work. But I was wondering if there was a reason for the ‘!=’ I’m just not seeing.


1 Like

Nah, the ‘!=’ was a bug and is already fixed in our sources (didn’t make the cut for 4.10).

Regarding our use of IGenericTeamAgentInterface, the reason only AIController is implementing it is because both IGenericTeamAgentInterface and AIController as well as most of AI stuff live in AIModule, that is optional. Engine knows nothing about it (in principle).

The internal projects that use it usually define their own “team agent” interface, that derives from IGenericTeamAgentInterface, and make both pawns and controllers derive from that (for ease of use). It’s usually the pawn that has the team information and functions implemented by controller just forward the call to pawn. Obviously we cache those values here and there for performance.


1 Like

Ah, ok. Great. I’ll fix it on our end.