Get uncorrect Unit Vector in increasing roll rotations

I am making line trace with LineTraceSingleByChannel which should emit rays as a cone like this

The beginning and the end of the ray trace is defined by a formula, that is:

const FVector StartTrace = SkipLength * UnitDirection + Origin
const FVector EndTrace = TotalLength * UnitDirection + Origin

where ‘UnitDirection’ is the unit vector of my rotation obtained by

rotation.vector()

It works well with increasing yaw rotations, but it always gave the same value to the unit vectors with increasing roll rotations. As a result, the line trace comes into a line like this:

Here is the data of my rotations and unit vectors.


Any advice to get the correct unit vector? Thx. (I would not like to rotate the whole cone 90°)

rotation.vector() gives you a vector facing in the direction of the rotator. Roll does not change direction, but orientation.

I believe what you are trying to achieve here, is rotate your angled vector around the world Z axis (which is what you achieve by incrementing Yaw), then rotate it around world X axis. Instead of converting rotator to vector, use a rotator to rotate your initial vector around the desired axis. There is a blueprint node to construct rotator from axis and angle.

Here is an example :

Thank you for your reply. After checking the source code, I finally found that rotation.vector() is in 2D space but not in 3D space, hence it is not affected by roll value. I can’t believe I have misunderstood it for such so long. :rofl:

BTW. What’s the fast way to get the vectors with increasing roll, zero yaw, fix pitch to a vertical plane (Normal vector is already known)? This is what I actually want to achieve.

Get my angled vectors first and then use dot product and their magnitude to the normal vector?

All your vectors have the same angle (dot) compared to the axis you rotate them around (in this case, 30° because pitch=30). Multiply them by a fixed distance and they’ll all be on a plane.

Base on your advice, what I need to do is get the unit vector (normalizes it) first and then get the fixed distance (by arcos30 with the normal). After that, multiply them together, am I correct?

Vector converted from rotation is already unit. Just multiply by an arbitrary distance (eg. 10000) and all your points will form a circle on a plane at 10000 distance.

This an idea on how I would tackle this:

.h
UFUNCTION(BlueprintCallable)
		static void ConeTracer(
			UPARAM() const AActor* Actor,
			UPARAM(ref) const int32 Index,
			UPARAM(ref) const float& TraceDistance, 
			UPARAM(ref) const float Radius, 
			UPARAM(ref) const int32 TotalTraces,
			FVector& TraceEnd
		);
.cpp
// .cpp
#include "Kismet/KismetMathLibrary.h"
#include "Math/Vector.h"

void UConeTracerFunctionLibrary::ConeTracer(
		UPARAM() const AActor* Actor,
		UPARAM(ref) const int32 Index,
		UPARAM(ref) const float& TraceDistance, 
		UPARAM(ref) const float Radius, 
		UPARAM(ref) const int32 TotalTraces,
		FVector& TraceEnd
)
{
	// Set variables.
	FVector ActorLocation = Actor->GetActorLocation();
	FVector ActorForwardVector = Actor->GetActorForwardVector();
	FVector ActorUpVector = Actor->GetActorUpVector();
	
	// Get Roll Angle
	float RollAmount = (TotalTraces > 1) ? (360.f / (float)TotalTraces) * Index : 0.f;
	// Roll up vector
	FVector RolledDir = UKismetMathLibrary::RotateAngleAxis(ActorUpVector, RollAmount, ActorForwardVector);
	// Set trace end location
	TraceEnd = (ActorForwardVector * TraceDistance + RolledDir * Radius) + ActorLocation;
}

Or the BP version:


Result
TraceInCone

You could change the AActor* parameter to to AActorComponent* and use it to direct the cone.


Edit: simplified the math.