No problem! Hope it helps.
I’ve bumped into a little bit of a roadblock. I was messing around with behavior trees and other stuff using blueprints when I got to the friendly, neutral, and hostile tick boxes on the AI perception component. I haven’t attempted any C++ in Unreal 4 until now. I find my knowledge of C++ rather lacking and foggy, but I attempted to follow this one guide anyways.
I wasn’t successful. I kept getting syntax errors messing with what code the guide had provided. My guess is because I didn’t #include the right stuff, although the guide didn’t specify anything that side of things. Does anybody have some other guides I should listen to that would help me with this subject? Or perhaps somebody might be able to replicate this small project for me and let me see their entire solution of the .cpp and .h files so that I can compare it to what I was trying to do so that I may reflect upon it?
What errors are you receiving. We’ve set it up in a prototype we made before, might be able to help.
Kind of hard to say. The compiler is acting kind of wonky right now.
Anwyays, for the header file, UCLASS() gets "this declaration has no storage class or type specifier, with class below it saying “expected a ‘;’”. I’m not sure what the heck I did wrong. Tried to add comments to the code with the errors, but when I do the compiler removes some of the syntax errors. I think a lot of the errors are related to the class anyways. I’ll post the header file.
.h file:
#pragma once
#include "GameFramework/Character.h"
#include "TestTeamCharacter.generated.h"
#include "GenericTeamAgentInterface.h" // THIS WAS ADDED! NOT FROM GUIDE.
UCLASS()
class TESTGAME_API ATestTeamCharacter : public ACharacter, public IGenericTeamAgentInterface // THIS WAS EDITTED!
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ATestTeamCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// THIS WAS ADDED!
private:
FGenericTeamId TeamId;
virtual FGenericTeamId GetGenericTeamId() const override;
};
What’s in your build.cs file?
Woops! The #include “TestTeamCharacter.h” is actually supposed to be “TestTeamCharacter.generated.h”. I was messing around that area and somehow removed it. I’ve editted the code box of the other comment to match what I have.
Anyways, a lot of stuff is broken. This compiler errors are coming in really slow right now. Forgot I was messing around with it because it was taking so long. The #include has an error that reads "cannot open source file “TestTeamCharacter.generated.h”.
That error is to be expected, generated.h are headers generated at compile time.
Oh wait, I found it I think. Tried using the solution explorer and it opened up a whole slew of folders from the game engine. Got kind of lost for a sec. Now I feel stupid.
using UnrealBuildTool;
public class Flicker : ModuleRules
{
public Flicker(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
Looks like you’re missing AIModule in your Build.cs file.
Should look like this.
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "AIModule", "GameplayTasks" });
using UnrealBuildTool;
public class TestGame : ModuleRules
{
public TestGame(TargetInfo Target)
{
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string[] { });
// Uncomment if you are using Slate UI
// PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" });
// Uncomment if you are using online features
// PrivateDependencyModuleNames.Add("OnlineSubsystem");
// To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true
}
}
Thank you for helping! Right now I’m not getting any syntax errors, but Visual Studio could just be wonky. I’ll need to see if this works out alright.
Do I need both the player and the NPC code from that example? Originally I thought I could get away with only 1, but perhaps team 255 considers everybody as neutral?
Checked back into the .cpp file and found out that I had 2 errors. ::ATestTeamCharacter has “no instance of overloaded function “ATestTeamCharacter::ATestTeamCharacter” matches the specified type”. The : just before Super has expected a ‘{’.
.cpp:
// Sets default values
ATestTeamCharacter::ATestTeamCharacter(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer) // THIS WAS EDITTED!
{
// 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;
TeamId = FGenericTeamId(0); // THIS WAS ADDED!
}
Try it like this.
ATestTeamCharacter::ATestTeamCharacter()
{
// 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;
TeamId = FGenericTeamId(0); // THIS WAS ADDED!
}
No errors in VS, compiled in Unreal with no errors. Didn’t test it though. Looks like I’ll need to set up the NPC side of things to get them out of the neutral team.
Yeah, you’ll have to give them a team id and also define how they react to teams.
Just tested some stuff I mocked up. They still only like to respond to neutral targets. My C++ code is getting no errors. Things that have changed from the original that I can tell would be the
(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
that was on the constructors of the .cpp files for both the player and the NPC. I’ll post the current code.
MyAIController.h
#include "AIController.h"
//#include "GenericTeamAgentInterface.h" // THIS WAS ADDED! NOT FROM GUIDE.
#include "MyAIController0.generated.h"
/**
*
*/
UCLASS()
class TESTGAME_API AMyAIController0 : public AAIController
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
AMyAIController0();
};
MyAIController.cpp
#include "TestGame.h"
#include "MyAIController0.h"
AMyAIController0::AMyAIController0()
{
// Assign to Team 1
SetGenericTeamId(FGenericTeamId(1));
}
TestTeamCharacter.h
#include "GameFramework/Character.h"
#include "GenericTeamAgentInterface.h" // THIS WAS ADDED! NOT FROM GUIDE.
#include "TestTeamCharacter.generated.h"
UCLASS()
class TESTGAME_API ATestTeamCharacter : public ACharacter, public IGenericTeamAgentInterface // THIS WAS EDITTED!
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
ATestTeamCharacter();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
// THIS WAS ADDED!
private:
FGenericTeamId TeamId;
virtual FGenericTeamId GetGenericTeamId() const override;
};
TeamTestCharacter.cpp
#include TestGame.h"
#include "TestTeamCharacter.h"
ATestTeamCharacter::ATestTeamCharacter()
{
// 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;
TeamId = FGenericTeamId(0); // THIS WAS ADDED!
}
// Called when the game starts or when spawned
void ATestTeamCharacter::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ATestTeamCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void ATestTeamCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
// THIS WAS ADDED!
FGenericTeamId ATestTeamCharacter::GetGenericTeamId() const
{
return TeamId;
}
Going to paste some more of our code here, hopefully will clear some things up. You have to explain to the perception component how to react to different teams. If you don’t everything is neutral.
HEADER
UCLASS()
class PROTOTYPE_API APrototypeAIController : public AAIController
{
GENERATED_BODY()
public:
APrototypeAIController();
protected:
UPROPERTY(EditDefaultsOnly)
FGenericTeamId TeamId;
public:
FGenericTeamId GetGenericTeamId() const override { return TeamId; }
ETeamAttitude::Type GetTeamAttitudeTowards(const AActor& Other) const override;
static ETeamAttitude::Type GetAttitudeTowards(FGenericTeamId TeamA, FGenericTeamId TeamB);
protected:
virtual ETeamAttitude::Type GetAttitudeTowardsPlayer(const AActor& Other) const;
};
CPP
APrototypeAIController::APrototypeAIController()
{
FGenericTeamId::SetAttitudeSolver(&APrototypeAIController::GetAttitudeTowards);
}
ETeamAttitude::Type APrototypeAIController::GetTeamAttitudeTowards(const AActor& Other) const
{
if (const APawn* OtherCharacter = Cast<APawn>(&Other))
{
if (const IGenericTeamAgentInterface* TeamAgent = Cast<IGenericTeamAgentInterface>(OtherCharacter->GetController()))
{
return Super::GetTeamAttitudeTowards(*OtherCharacter->GetController());
}
return GetAttitudeTowardsPlayer(Other);
}
return ETeamAttitude::Neutral;
}
ETeamAttitude::Type APrototypeAIController::GetAttitudeTowards(FGenericTeamId TeamA, FGenericTeamId TeamB)
{
return TeamA == TeamB ? ETeamAttitude::Friendly : ETeamAttitude::Hostile;
}
ETeamAttitude::Type APrototypeAIController::GetAttitudeTowardsPlayer(const AActor& Other) const
{
return ETeamAttitude::Hostile;
}
Man, I’ve got a lot to take in. I might take a break for today. I’ll keep a note to look at what I believe to be associated with the team system (AIInterfaces.cpp?) and to look through what you’ve shown me to make more sense of it all. I’d like to thank you for your help and kindness, HailstoneRyan.
Hello I’ve just released a tutorial updated to Unreal 4.22 about this topic:
In a few words: The AAIController
class implements the GenericTeamAgentInterface
, you can inherits from AAIController
, override the GetTeamAttitudeTowards
function and setup a TeamID
depending on your needs.
Check this Gist for full code or the article for more details.