What’s the proper way to do this now? I added the interface IGenericTeamAgentInterface. But I have no idea how to set the actual (const) member. All I could find was:
I set the interface in C++:
#include "Runtime/AIModule/Classes/GenericTeamAgentInterface.h"
class AFPS1Character : public ACharacter, public IGenericTeamAgentInterface
But it crashes: Assertion failed: bCreateOnlyIfEmpty || !PointerToUberGraphFrame->RawPointer [File:D:\BuildFarm\buildmachine_++UE4+Release-4.11\Engine\Source\Runtime\Engine\Private\BlueprintGeneratedClass.cpp] [Line: 647]
There is no build-in struct-member for Enemy, Player & Neutral. Does that mean we have to create those ourselves as well? Only FGenericTeamId::NoTeam is present.
GetGenericTeamId provides ID of the team only. GetTeamAttitudeTowards logic provides attittude to unit (Enemy, Neutral or Friendly). At the moment there is no version of these functions for use in blueprints.
Sorry I can’t get it to compile. Also can’t really make our own enum for it. We have to use the one UE4 uses in it’s interface ( FGenericTeamId | Unreal Engine Documentation ) and extend that. But C++ does not really support it. And you end up with gigantic workarounds. I give up.
I’m going back to PawnSensing. I know it’s ‘deprecated’ but at least it works. This is too much of a mess just to set a very very simple enum on the player actor…
I’ll mark it as answered since you are pointing in the right direction but my C++ knowledge is just not advanced enough yet to do this.
I gave it another try without hacking around first. But it always returns neutral because OtherTeamAgent always evaluates to false. And I was so close…
Still, the amount of C++ knowledge needed for this is quite advanced. You need knowledge about: inheritance, overriding with different scopes, virtuals + constants, references, extending enums (EPredefinedId), etc. etc. How are people using only blueprints supposed to implement this? Also the internal code looks ‘odd’, may need some refactoring.
Not sure but I may also have to set the TeamID it seems.
// header file (did the same to the playercontroller)
#pragma once
#include "AIController.h"
#include "FPS1AIController.generated.h"
/**
* AAIController already implements the IGenericTeamAgentInterface so don't add it here.
*/
UCLASS()
class FPS1_API AFPS1AIController : public AAIController
{
GENERATED_BODY()
public:
virtual FGenericTeamId GetGenericTeamId() const { return ETeamAttitude::Hostile; }
// WHY is this method private (in their interface) while their static solver is public?
// WHY do they use both a solver and this method? Why so complicated?
virtual ETeamAttitude::Type GetTeamAttitudeTowards(const AActor& Other) const
{
const IGenericTeamAgentInterface* OtherTeamAgent = Cast<const IGenericTeamAgentInterface>(&Other);
if (OtherTeamAgent) // <<<<<<<< always evaluates to false? WHY?
{
UE_LOG(LogTemp, Error, TEXT("checking"))
return OtherTeamAgent->GetGenericTeamId() ? ETeamAttitude::Hostile : ETeamAttitude::Neutral;
//return ETeamAttitude::Hostile;
//return OtherTeamAgent->GetGenericTeamId() != GetGenericTeamId() ? ETeamAttitude::Hostile : ETeamAttitude::Friendly;
}
else
{
UE_LOG(LogTemp, Error, TEXT("neutral"))
return ETeamAttitude::Neutral;
}
}
};
GetGenericTeamId is public anywhere (Interface or implementation) and GetTeamAttitudeTowards too.
OtherTeamAgent is nullptr because Pawn (Actor) in argument has not IGenericTeamAgentInterface’s implementation. I usually do Cast to the desired type of Pawn and check its diplomacy.
My K2 version is working and you can edit logic in BP. For GetGenericTeamID also need to use a K2 wrapper.
GetTeamAttitudeTowards too. OtherTeamAgent is nullptr because Pawn (Actor) in argument has not IGenericTeamAgentInterface’s implementation.
I put 2 enemies (same blueprint) opposite of each other and making them look at one another, thus both having the interface. So if one of them has the implementation, the other one MUST have too it can not be null. Yet I get only null-values for the other agent variable.
I applied your latest code example but again the same problem. I’m really going back to pawnsensing because this new aiperception is just unfinished imo. I’m sure some people hack their way around and and that others use dirty workarounds and perhaps some people get it properly to work. But I’m not one of those. And pawnsensing is like 10 minutes to imlement.
@Napoleon, from how you’ve described your issue, it sounds like your sensing component is (correctly) on your AIController subclass. However, the perception is picking up your AI agent’s Character object and not its AIController object. Since your Character object doesn’t implement the IGenericTeamAgentInterface (it’s AIController does), the interface cast fails and you always get OtherTeamAgent == nullptr. You can get around this by creating a subclass of Character for your AI to use which also implements IGenericTeamAgentInterface. In this class, you’d simply return the Character’s AIController’s TeamID. You’ll need to do something similar for PlayerController as well if your player is going to be on a team. If you’re feeling like this is a lot of work to do to set an int property, you are wrong. But hopefully this will help you get everything sorted. =)
I see that this is still a problem in 4.21.1.
It can not be so difficult to fix something like that, and that you can edit from blueprint, at least be able to choose if an actor is, friend, neutral or enemy.
it seems like from my little experienced once a feature is ready, they never go back and add stuff to it, so if they for some reason decided not to add that option to blueprint it will never be possible… there is many small stuff like that