Hey,
In short, my problem is that of the two characters I spawn (same blue print) one character gets correct OtherBodyIndex and other one only -1?
So I have a custom character class, for a local PvsP fighting game, which I made a blueprint from. Then wrote a custom ActorComponent for hit detection.
The GameMode spawns 2 of these Character Blueprints on start then some logic set one to Red player and the other to Blue player for collision and such. They get a collision profile that was added to the DefaultEngine.ini. Anyway since it’s one character they run the exact same logic (with the difference of being filter and set to red and blue).
so by being spawned this BeginPlay set red/blue:
void AMTCPlayerState::BeginPlay()
{
//Initialize State with Red or Blue based upon character
AMTCGameModeBase* GM = Cast<AMTCGameModeBase>(GetWorld()->GetAuthGameMode());
//Find the characters to Init them
TArray<AActor*> outCharacters;
//TODO: Stop this search being done twice without making it static
UGameplayStatics::GetAllActorsOfClass(GetWorld(), AMTCCharacter::StaticClass(), outCharacters);
for (int i = 0; i < outCharacters.Num(); i++) {
AMTCCharacter* ch = Cast<AMTCCharacter>(outCharacters*);
//Error Check
if (!ch->PlayerState) {
UE_LOG(LogTemp, Error, TEXT("Characters dont have an associated PlayerState!!"));
return;
}
//If the correct player
if (ch->PlayerState->PlayerId == PlayerId) {
#ifdef PlayerStateHasRefToCharacter
character = ch; //Set Ref from State back to Player
UE_LOG(LogTemp, Warning, TEXT("Player: %c"), (ACharacter*)ch == GM->redPlayer->GetCharacter() ? 'r' : 'b');
#endif
if ((ACharacter*)ch == GM->redPlayer->GetCharacter()) //Red
Init(true, Cast<AMTCCharacter>(GM->bluePlayer->GetCharacter())); //Init Red
else //Blue
Init(false, Cast<AMTCCharacter>(GM->redPlayer->GetCharacter())); //Init Blue
ch->Init(); //Init Character
break;
}
}
}
void AMTCPlayerState::Init(bool isRedPlayer, AMTCCharacter* opponent)
{
if (isInitalized)
return;
isInitalized = true;
//Setup
this->opponent = opponent;
this->isRedPlayer = isRedPlayer;
this->SetActorLabel(this->GetActorLabel() + (isRedPlayer ? AMTCGameModeVersus::RED_PLAYER_ACTOR_SUFFIX : AMTCGameModeVersus::BLUE_PLAYER_ACTOR_SUFFIX));
#ifdef PlayerStateHasRefToCharacter
//Set collision preset
UImpactPhysics* impactPhysics = Cast<UImpactPhysics>(character->GetComponentByClass(UImpactPhysics::StaticClass()));
impactPhysics->Init(isRedPlayer);
#endif
}
then this line:
UImpactPhysics* impactPhysics = Cast<UImpactPhysics>(character->GetComponentByClass(UImpactPhysics::StaticClass()));
impactPhysics->Init(isRedPlayer);
runs ImpactPhysics’ init (which is the hit detection component):
void UImpactPhysics::Init(bool isRed)
{
//Get SkeletalMesh and subscribe to OnBeginOverlap
USkeletalMeshComponent* mesh = Cast<USkeletalMeshComponent>(GetOwner()->GetComponentByClass(USkeletalMeshComponent::StaticClass()));
if (mesh)
{
mesh->OnComponentBeginOverlap.AddDynamic(this, &UImpactPhysics::OnOverlapBegin);
if (isRed)
{
UE_LOG(LogTemp, Warning, TEXT("Character Red"));
mesh->BodyInstance.SetCollisionProfileName(TEXT("Red"));
}
else
{
UE_LOG(LogTemp, Warning, TEXT("Character Blue"));
mesh->BodyInstance.SetCollisionProfileName(TEXT("Blue"));
}
mesh->SetGenerateOverlapEvents(true);
mesh->bMultiBodyOverlap = true;
}
}
the collision profiles are set to red ignore red and overlap blue and visa versa. This all seems to work fine.
as you can see OnOverlapBegin subscribed to OnComponentBeginOverlap, and the OnOverlapBegin is:
void UImpactPhysics::OnOverlapBegin(UPrimitiveComponent * HitComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
AMTCCharacter* opponent = Cast<AMTCCharacter>(OtherActor);
UImpactPhysics* opponentImpact = Cast<UImpactPhysics>(opponent->GetComponentByClass(UImpactPhysics::StaticClass()));
USkeletalMeshComponent* opponentMesh = Cast<USkeletalMeshComponent>(OtherComp);
if (opponentMesh)
{
AMTCCharacter* character = Cast<AMTCCharacter>(GetOwner());
if (OtherBodyIndex > -1)
{
FBodyInstance* bI = opponentMesh->Bodies[OtherBodyIndex];
UE_LOG(LogTemp, Warning, TEXT("Attacker: %s | OtherBodyIndex: %d"), *character->GetName(), OtherBodyIndex);
}
else
UE_LOG(LogTemp, Warning, TEXT("Character: %s | OtherBodyIndex: %d"), *character->GetName(), OtherBodyIndex);
}
}
and the log result is: