GAS - GetAvatarActorFromActorInfo() is returning a controller, not the character

In running some GAS tutorials I have noted that the use of GetAvatarActorFromActorInfo() as it applies to a UGameplayAbility is being used to return a character.

When I use it, it returns a Player Controller.

Did something change to alter this return type? Existing code that was once working casting to interfaces on the character are now broken because a Controller is being passed back instead, so code needs tweaked to check for the character in the controller.

I ask the question because it may be that I’m now simply using it wrong and I cannot find information on this when I look around.

To add some examples:

FVector UMetaliaProjectileSpell::GetSocketLocationFromExecutingActor() const
{
	// now for lolz we have to figure out why the actor coming in is not my character who should be implementing ICombatInterface
	AActor* MyCurrentActor = GetAvatarActorFromActorInfo();
	ICombatInterface* Combat = Cast<ICombatInterface>(MyCurrentActor);

	if (!Combat)
	{
		// if it passed back the Controller, you need to dig the character out of that
		// if it did not pass back a controller and something else is haywire, thats bad.

		// this could be a problem with AI controlled items but we shall see
		AMetaliaPlayerController* Controller = Cast<AMetaliaPlayerController>(MyCurrentActor);
		check(Controller);

		MyCurrentActor = Cast<AMetaliaCharacterBase>(Controller->GetCharacter());
		check(MyCurrentActor);
	}
		
	return ICombatInterface::Execute_GetProjectileSocketLocation(MyCurrentActor);
}

Note here I am having to cast the avatar actor to a character before I can cast that to my interface, where as far as I know, the call to GetAvatarActorFromActorInfo should have been giving me my character.

Here is a second example. This is in a GAS Gameplay Ability where I am wanting to play a montage on the activation of the ability. In blueprint, I should just be able to fire PlayMontageAndWait but that node implicitly goes behind the scenes to get the avatar actor… which in my case is for whatever reason a controller, and then fails. So I have to weave magical hoops and use a more traditional Play Anim Montage:

I shouldn’t have to do these things. The Avatar Actor SHOULD be a character, but I can find very little out there that helps me understand why in my case its being set to a controller.

This is Unreal 5.3.2

It’s been a while since I’ve used GAS, but if I recall, Avatar Actor will only give you the character if you setup GAS in a very specific way.
Additionally, when using GAS, you’re going to have quite a bit of boilerplate. It’s not really avoidable so I suggest making utility functions for it when you notice it.

One of the things I started was that very boilerplate to retrieve my avatar actor’s CHARACTER since this will crop up a lot.

I can’t find any information on having to set up GAS to make it so my avatar actor is the character. Do you know any good starting points? I never even read that this was configurable in this way.

There’s some community documentation which talks about it here.
You likely have to set the Avatar Actor to the Character yourself when you create the GAS ASC Component. I believe there’s also an Interface you have to implement called GetAbilitySystemComponent.

Cool so I went over all that last night and found I was doing exactly those things already.

The code image above is from my Character. As the documentation tells us to do when player state owns the Ability Component, we should initialize it in PossessedBy and in OnRep_PlayerState, which the code shows is being done.

This code is running and delving into the InitAbilityActorInfo method, should be setting an avatarActor variable to the character class (the second parameter, or “this” in the image).

However… something is happening somewhere else to turn this to the Player Controller.

And thus I will dig around to see if I can’t find the call that is leading to this happening. I appreciate your starting point - it has been very helpful.