Weird rotator results when calculating the rotation between two vectors

Apparently I just don’t understand vector math any more because I have encountered nonstop agony with this problem. What’s more aggravating is that it should be a fairly simple, straightforward calculation, but it’s been anything but. I have looked through the other answers and examples, in addition to trying to drill down into each value and figure out what’s causing the weirdness, but to no avail.

First, the situation:

  • I am implementing thrown objects in a 3D sidescroller game.
  • I am implementing it in C++
  • I made a “projectile” class with, currently, just a mesh and projectilemovement component.
  • I have the below code that:
  1. gets the location vector of the currently held object as a point of origination

  2. gets the vector location of the mouse

  3. calculates the vector between the two points

  4. calculates the pitch (in theory)

  5. creates the projectile at the previously mentioned origination point with the rotator calculated in the previous step and let’s the movement component take over from there

    FVector EquipmentLocationLocal = GetActorLocation();

    FVector MouseLocationLocal;
    FVector MouseRotationLocal;
    GetWorld()->GetFirstPlayerController()->DeprojectMousePositionToWorld(MouseLocationLocal, MouseRotationLocal);

    MouseLocationLocal.X = 0.f;
    EquipmentLocationLocal.X = 0.f;

    FVector NewVectorLocal = MouseLocationLocal - EquipmentLocationLocal;
    FRotator SpawnRotationLocal = FRotationMatrix::MakeFromY(NewVectorLocal).Rotator();

    AEquipmentProjectile* ProjectileLocal = GetWorld()->SpawnActor(AEquipmentProjectile::StaticClass(), EquipmentLocationLocal, SpawnRotationLocal);

The results:

The projectile is launched only in the direction the character is facing, regardless of the mouse being in front or in back of the character, at around 40 degrees. Moving the mouse has only the most minute effect on the angle, hence why I used the word “around”. Here is a picture to illustrate, where yellow is the point the projectile originates from, red is about where the mouse is (apparently print screen doesn’t capture the mouse anymore…?), and green is where the projectile is:

At this point, I’m not quite sure what the issue is. I have no doubt it’s with my setup, but I don’t know where. I zero out the x values of the original 2 vectors because using them gave weirder results and I don’t want the equation to be concerned with calculations on the x axis. I feel like this is just a band-aid to a perceived problem that has roots in the larger issue. I also don’t understand why, when using MakeFromY, the roll and yaw are set to +/-90 degrees.

I also thought that the problem may lay in the fact that I was using the location of the item being thrown, when I should be using a location based on the object “holding” it. This only allowed the projectile to be thrown in back of or in front of the character and decreased the calculated pitch to around 5 degrees.

When printed, all the values I use to create the new rotator, on investigation, return feasible numbers that change when the mouse or character, respectively, are moved (sans the x axis value, because that’s the axis no movement occurs in and, as such, is expected).

Any help or advice on this issue would be ridiculously appreciated.

1 Like

Well, I finally figured it out. I wish someone would have told me that more needs to be done with DeprojectMousePositionToWorld to get a usable mouse location as that was basically the main offender problem.

In any case, for anyone who’s looking to get a similar effect in their game, here’s what I do to fire a projectile at the mouse location from a held weapon in the character’s hand:

//get the current mouse and equipment location
FVector EquipmentLocationLocal = GetActorLocation(); 
FVector MouseLocationLocal;
FHitResult HitResult;
GetWorld()->GetFirstPlayerController()->GetHitResultUnderCursor(ECC_Visibility,  false, HitResult);
	
if (HitResult.bBlockingHit)
{
	MouseLocationLocal = HitResult.ImpactPoint;
}

//calculate the angle of the vector from the equipment to mouse, ignoring the X value
FVector NewVectorLocal = MouseLocationLocal - EquipmentLocationLocal;
NewVectorLocal.X = 0;
FRotator SpawnRotationLocal = FRotationMatrix::MakeFromX(NewVectorLocal).Rotator();
SpawnRotationLocal.Pitch, SpawnRotationLocal.Yaw, SpawnRotationLocal.Roll));

AEquipmentProjectile* ProjectileLocal = GetWorld()->SpawnActor<AEquipmentProjectile>(AEquipmentProjectile::StaticClass(), EquipmentLocationLocal, SpawnRotationLocal);

I’m sure it’s not pretty, so anyone can feel free to correct anything about it, but all the components needed are there. The essential parts was using GetHitResultUnderCursor for the mouse location in world.