Hi,
I would like to code a cascading raycast like this:
Source point = position of the emitting object
I choose 4 directions (I could have chosen a different number)
Four raycasts are generated from this source point to strike a first object at 4 impact points, each of which in turn becomes a source of four raycasts to strike a second object, etc.
So I coded a C++ class called RayEmitter2, whose .h:
//RayEmitter2.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RayEmitter2.generated.h"
UCLASS()
class ESSAI_API ARayEmitter2 : public AActor
{
GENERATED_BODY()
public:
ARayEmitter2();
protected:
virtual void BeginPlay() override;
public:
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
AActor* EmitterActor;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
TArray<FVector> EmissionDirections;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
float RayLength = 1000.0f;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
int32 MaxGenerations = 3;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
FLinearColor LineColor = FLinearColor::Yellow;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
float LineThickness = 1.0f;
UPROPERTY(EditAnywhere, Category = "Ray Emission")
float RayDisplayDuration = 1.0f; // Ajout de la durée d'affichage
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
int32 nb_appel = 0;
// Liste des points d’impact pour chaque génération
TArray<TArray<FVector>> ImpactGenerations;
protected:
// Gère les rayons pour un seul point source
TArray<FVector> GenerateRaysFromSinglePoint(const FVector& Source);
};
and whose cpp is:
//RayEmitter2.cpp
#include "RayEmitter2.h"
#include "DrawDebugHelpers.h"
#include "Engine/World.h"
//2 problèmes:
//les points d'impact de la 2nd génération sont les mêmes
//le 2nd objet touché est le même que lEr objet touché
// Constructeur
ARayEmitter2::ARayEmitter2()
{
PrimaryActorTick.bCanEverTick = true;
}
// BeginPlay
void ARayEmitter2::BeginPlay()
{
Super::BeginPlay();
if (!EmitterActor)
{
UE_LOG(LogTemp, Warning, TEXT("EmitterActor non défini"));
return;
}
ImpactGenerations.Empty();
// Génération 0 = EmitterActor (point de départ)
TArray<FVector> CurrentSources;
CurrentSources.Add(EmitterActor->GetActorLocation());
ImpactGenerations.Add(CurrentSources);
UE_LOG(LogTemp, Warning, TEXT("Démarrage des générations de rayons. MaxGenerations: %d"), MaxGenerations); // Ajout de ce log
UE_LOG(LogTemp, Warning, TEXT("Résumé des impacts par génération :"));
for (int32 Gen = 0; Gen < MaxGenerations; ++Gen)
{
UE_LOG(LogTemp, Warning, TEXT("Génération %d, Nombre de sources: %d"), Gen, CurrentSources.Num()); // Ajout de ce log
TArray<FVector> NewImpactsThisGeneration;
TArray<FVector> NextGenerationSources; // Pour stocker les points d'impact de cette génération
NewImpactsThisGeneration.Empty();
NextGenerationSources.Empty();
for (const FVector& Source : CurrentSources)
{
// Émettre des rayons depuis la source actuelle
TArray<FVector> ImpactsFromSource = GenerateRaysFromSinglePoint(Source);
NewImpactsThisGeneration.Append(ImpactsFromSource);
NextGenerationSources.Append(ImpactsFromSource); // Préparer les sources pour la prochaine génération
/*
// 🔹 Log des points sources (CurrentSources)
FString SourcesStr;
for (const FVector& Src : CurrentSources)
{
SourcesStr += FString::Printf(TEXT("%s, "), *Src.ToString());
}
UE_LOG(LogTemp, Warning, TEXT("Génération %d - Points source: %s"), Gen, *SourcesStr);
// 🔹 Log des impacts trouvés
FString ImpactsStr;
for (const FVector& Impact : ImpactsFromSource)
{
ImpactsStr += FString::Printf(TEXT("%s, "), *Impact.ToString());
}
UE_LOG(LogTemp, Warning, TEXT("Génération %d - Points d'impact: %s"), Gen, *ImpactsStr);*/
}
if (NewImpactsThisGeneration.Num() == 0)
{
UE_LOG(LogTemp, Warning, TEXT("Génération %d: Aucun nouvel impact trouvé. Arrêt."), Gen); // Ajout de ce log
break;
}
ImpactGenerations.Add(NewImpactsThisGeneration);
CurrentSources = NextGenerationSources; // Les nouveaux impacts deviennent les sources pour la prochaine génération
UE_LOG(LogTemp, Warning, TEXT("Génération %d: %d nouveaux impacts trouvés."), Gen, NewImpactsThisGeneration.Num()); // Ajout de ce log
}
UE_LOG(LogTemp, Warning, TEXT("Fin des générations de rayons.")); // Ajout de ce log
}
// Tick
void ARayEmitter2::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
TArray<FVector> ARayEmitter2::GenerateRaysFromSinglePoint(const FVector& Source)
{
nb_appel++;
TArray<FVector> ImpactPoints;
ImpactPoints.Empty();
UE_LOG(LogTemp, Warning, TEXT("GenerateRaysFromSinglePoint %d fois appelé depuis: %s"),nb_appel, *Source.ToString()); // Ajout de ce log
for (const FVector& Direction : EmissionDirections)
{
UE_LOG(LogTemp, Warning, TEXT(" Direction: %s"), *Direction.ToString()); // Ajout de ce log
FVector DirNormalized = Direction.GetSafeNormal();
FVector End = Source + DirNormalized * RayLength;
FHitResult Hit;
FCollisionQueryParams Params;
Params.AddIgnoredActor(this);
if (EmitterActor)
Params.AddIgnoredActor(EmitterActor);
bool bHit = GetWorld()->LineTraceSingleByChannel(
Hit,
Source,
End,
ECollisionChannel::ECC_Visibility,
Params
);
if (bHit)
{
UE_LOG(LogTemp, Warning, TEXT(" Normale: %s"), *Hit.ImpactNormal.ToString());
ImpactPoints.Add(Hit.ImpactPoint);//avant
// Décale légèrement le point d'impact dans la direction de la normale pour éviter de toucher la même surface
//FVector AdjustedImpactPoint = Hit.ImpactPoint + Hit.ImpactNormal * 1.0f;
//ImpactPoints.Add(AdjustedImpactPoint);
UE_LOG(LogTemp, Warning, TEXT(" Impact à: %s"), *Hit.ImpactPoint.ToString()); // Ajout de ce log
/*UE_LOG(LogTemp, Warning, TEXT(" Touche: %s à %s"),
*Hit.GetActor()->GetName(),
*Hit.ImpactPoint.ToString());*///avant
UE_LOG(LogTemp, Warning, TEXT(" Touche: %s (ptr: %p) à %s"),
*Hit.GetActor()->GetName(),
Hit.GetActor(),
*Hit.ImpactPoint.ToString());
// Debug visual
//le 3ème paramètre de DrawDebugLine est un point(pas une direction)
//DrawDebugLine(GetWorld(), Source, AdjustedImpactPoint, LineColor.ToFColor(true), false, RayDisplayDuration, 0, LineThickness);
//DrawDebugPoint(GetWorld(), AdjustedImpactPoint, 8.0f, FColor::Red, false, RayDisplayDuration);
DrawDebugLine(GetWorld(), Source, Hit.ImpactPoint, LineColor.ToFColor(true), false, RayDisplayDuration, 0, LineThickness);//avant
DrawDebugPoint(GetWorld(), Hit.ImpactPoint, 8.0f, FColor::Red, false, RayDisplayDuration);//avant
}
else
{
UE_LOG(LogTemp, Warning, TEXT(" Pas d'impact. Fin du rayon: %s"), *End.ToString()); // Ajout de ce log
DrawDebugLine(GetWorld(), Source, End, FColor::Red, false, 1.0f, 0, LineThickness);
}
}
UE_LOG(LogTemp, Warning, TEXT("GenerateRaysFromSinglePoint terminé. %d impacts trouvés."), ImpactPoints.Num()); // Ajout de ce log
return ImpactPoints;
}
Here’s what the output log gives me:
LogTemp: Warning: Démarrage des générations de rayons. MaxGenerations: 2
LogTemp: Warning: Résumé des impacts par génération :
LogTemp: Warning: Génération 0, Nombre de sources: 1
LogTemp: Warning: GenerateRaysFromSinglePoint 1 fois appelé depuis: X=1881.093 Y=2823.205 Z=75.063
LogTemp: Warning: Direction: X=1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.000 Y=0.000 Z=-1.000
LogTemp: Warning: Impact à: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.000 Y=0.000 Z=-1.000
LogTemp: Warning: Impact à: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.000 Y=0.000 Z=-1.000
LogTemp: Warning: Impact à: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.000 Y=0.000 Z=-1.000
LogTemp: Warning: Impact à: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: GenerateRaysFromSinglePoint terminé. 4 impacts trouvés.
LogTemp: Warning: Génération 0: 4 nouveaux impacts trouvés.
LogTemp: Warning: Génération 1, Nombre de sources: 4
LogTemp: Warning: GenerateRaysFromSinglePoint 2 fois appelé depuis: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=3017.643 Z=269.500
LogTemp: Warning: GenerateRaysFromSinglePoint terminé. 4 impacts trouvés.
LogTemp: Warning: GenerateRaysFromSinglePoint 3 fois appelé depuis: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=2075.531 Y=2628.768 Z=269.500
LogTemp: Warning: GenerateRaysFromSinglePoint terminé. 4 impacts trouvés.
LogTemp: Warning: GenerateRaysFromSinglePoint 4 fois appelé depuis: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=3017.643 Z=269.500
LogTemp: Warning: GenerateRaysFromSinglePoint terminé. 4 impacts trouvés.
LogTemp: Warning: GenerateRaysFromSinglePoint 5 fois appelé depuis: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=-0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=-0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Direction: X=-1.000 Y=-1.000 Z=1.000
LogTemp: Warning: Normale: X=0.577 Y=0.577 Z=-0.577
LogTemp: Warning: Impact à: X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: Touche: StaticMeshActor_UAID_0042C04F8026175D02_1540545753 (ptr: 00000718B7BCD700) à X=1686.656 Y=2628.768 Z=269.500
LogTemp: Warning: GenerateRaysFromSinglePoint terminé. 4 impacts trouvés.
LogTemp: Warning: Génération 1: 16 nouveaux impacts trouvés.
LogTemp: Warning: Fin des générations de rayons.
2 problems I can’t solve:
The impact points of the second generation are the same
The second object hit is the same as the first object hit
Here’s what I get:
Here’s what I should get:
Can you help me?
thanks