Lyra Weapon Wall Trace

Hello,

In ULyraGameplayAbility_RangedWeapon there is this ELyraAbilityTargetingSource enum that i’m mostly interested in using WeaponTowardsFocus from it in order to hit walls if it’s in the way between the gun and the target. Currently if you change

const FTransform TargetTransform = GetTargetingTransform(AvatarPawn, ELyraAbilityTargetingSource::CameraTowardsFocus);

to

const FTransform TargetTransform = GetTargetingTransform(AvatarPawn, ELyraAbilityTargetingSource::WeaponTowardsFocus);

The trace would start from the actor and not from the weapon, and the trace end is not accurate at all, mostly because the GetWeaponTargetingSourceLocation function is still not fully implemented to handle all the cases.

Has anyone managed to make this work properly?

Modifying the WeaponTrace function actually did the trick

FHitResult ULyraGameplayAbility_RangedWeapon::WeaponTrace(const FVector& StartTrace, const FVector& EndTrace, float SweepRadius, bool bIsSimulated, OUT TArray<FHitResult>& OutHitResults) const
{
	TArray<FHitResult> HitResults;

	FCollisionQueryParams TraceParams(SCENE_QUERY_STAT(WeaponTrace), /*bTraceComplex=*/ true, /*IgnoreActor=*/ GetAvatarActorFromActorInfo());
	TraceParams.bReturnPhysicalMaterial = true;
	AddAdditionalTraceIgnoreActors(TraceParams);
	//TraceParams.bDebugQuery = true;

	const ECollisionChannel TraceChannel = DetermineTraceChannel(TraceParams, bIsSimulated);

	if (SweepRadius > 0.0f)
	{
		GetWorld()->SweepMultiByChannel(HitResults, StartTrace, EndTrace, FQuat::Identity, TraceChannel, FCollisionShape::MakeSphere(SweepRadius), TraceParams);
	}
	else
	{
		GetWorld()->LineTraceMultiByChannel(HitResults, StartTrace, EndTrace, TraceChannel, TraceParams);
	}

	FHitResult Hit(ForceInit);
	if (HitResults.Num() > 0)
	{
		// Filter the output list to prevent multiple hits on the same actor;
		// this is to prevent a single bullet dealing damage multiple times to
		// a single actor if using an overlap trace
		for (FHitResult& CurHitResult : HitResults)
		{
			auto Pred = [&CurHitResult](const FHitResult& Other)
			{
				return Other.HitObjectHandle == CurHitResult.HitObjectHandle;
			};

			if (!OutHitResults.ContainsByPredicate(Pred))
			{
				OutHitResults.Add(CurHitResult);
			}
		}

		Hit = OutHitResults.Last();

		// Perform an additional line trace to check for obstacles ignoring the valid target
		FHitResult ObstacleHit;
		if (Hit.GetActor())
		{
			TraceParams.AddIgnoredActor(Hit.GetActor());
		}

		FVector StartTrace_Obstacle = StartTrace;
		if (AActor* WeaponActor = GetFirstSpawnedWeaponActor())
		{
			StartTrace_Obstacle = WeaponActor->GetActorLocation();
		}

		bool bHitObstacle = GetWorld()->LineTraceSingleByChannel(ObstacleHit, StartTrace_Obstacle, Hit.ImpactPoint, TraceChannel, TraceParams);
		if (bHitObstacle && ObstacleHit.GetActor())
		{
			// If an obstacle is hit, clear the OutHitResults and add the obstacle hit
			OutHitResults.Empty();
			OutHitResults.Add(ObstacleHit);
			Hit = ObstacleHit;
		}
	}
	else
	{
		Hit.TraceStart = StartTrace;
		Hit.TraceEnd = EndTrace;
	}

	return Hit;
}

Can add a bool for whether the weapon should do the check for the obstacle or not etc…

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.