Character follow mouse cursor

void ALongpakt::SetLocation()
{
APlayerController* MyController = GetWorld()->GetFirstPlayerController();
float x, y;
FVector MouseLoc = MyController->GetMousePosition(x, y);
ALongpakt::SetActorLocation(MouseLoc, false);
}

How would I make the character always at the mouse position?

Yes, I want it constantly teleported to the cursor.

I’m not sure what you are trying to do…

Do you want your character to

  • look at the mouse cursor?

  • move to the mouse cursor?

  • or constantly be teleported to the mouse cursor? (because that’s what SetActorLocation does…)

Ok, but the mouse position you are getting from the controller are just flat screen coordinates. You can use APlayerController::GetHitResultUnderCursor to do a line-trace into the world and receive a 3D-location in the FHitResult-struct. That’s where you want to place your actor.

How would I make the character always at the mouse position?

Hello Pikachu1001000,

that’s actually a quite complicated question. The easiest way would be to teleport the player at the exact position of the mouse cursor every frame. The “teleporting” part is very important because it would allow us not to worry about differ mouse speed which people have.

You can use this function APlayerController::DeprojectMousePositionToWorld:

Then set the character world position to deprojected world position with this:

Repeat every frame. Remember, that you can show or hide the mouse cursor using PlayerController api (good for testing):

Also, there might be some problems with collision so be sure to uncheck sweep and I’m not sure how the function to deproject mouse position would behave without any floor.

The second part which I’d like to consider is to actually order the character to move to the cursor world location. You can do this without worrying about speed of the character but it would totally change the resulting mechanics. The slower character would try to chase the quickly flying mouse, changing the direction of movement before reaching the previous placement of the cursor.

In this case you would have to get the value of mouse delta:

Then calculate the speed of the mouse by dividing delta location by tick delta seconds. Probably, it should be done using vectors in real world, so deproject two screen mouse locations to world space, then calculate the displacement:

https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Math/FVector/op_sub/1/index.html
and the result put here:
https://docs.unrealengine.com/latest/INT/API/Runtime/Core/Math/FVector/Size/index.html

Now you have the delta of the mouse in world space displacement float, aka path. Now easily divide path by time and you can affect character using this computed speed. In this case just use:

Hope it will help. :slight_smile:

Regards,
Taberu

P.S.

void ALongpakt::SetLocation() { APlayerController* MyController = GetWorld()->GetFirstPlayerController(); (...)

This is a very dangerous style. I’m aware that UWorld is usually there when we consider an actor existence but we should always assume it might be NULL, then the operator → would crash. GetFirstPlayerController is even more possible to be NULL. We have to check both inside of the body function anyway, so I think this style is exaggeration. I don’t even know how it compiled when you didn’t assign default values to second argument of the function (default values should be last).

But please, don’t consider it as an attack, I just have to express my opinion, I might be wrong. Cheers! :slight_smile:

Can you give me an example on how to do this exactly?

Sadly, that would require me to do all the work for you. Sorry, I don’t have as much free time as I would like to. And I’m also involved in my personal projects. My description should be enough. If not, then try to do something simpler for the start. Good luck!

Okay, so here is what I have:
void ALongpakt::SetLocation()
{
FVector mouseLocation, mouseDirection;
APlayerController* MyController = GetWorld()->GetFirstPlayerController();
MyController->DeprojectMousePositionToWorld(mouseLocation, mouseDirection);
SetActorLocation(mouseLocation, false);
}

When I begin the game, my character goes flying up in the air. This is a top-down game.

First of all, couldyounowwriteyourcodelikethat? It’sannoying.

As I wrote - I wasn’t sure, how DeprojectMousePositionToWorld() would behave if there is no floor. Apparently, it doesn’t even care about those things. Does returned Z value depend on camera location?

In this simple case, you can still try use this function, just put into SetActorLocation’s Z value Character’s current Z location (GetActorLocation()).

I also found in this very moment, how it’s done in top-down template you are using. There is everything you need…
They are not using DeprojectMousePositionToWorld(). They trace the location of the mouse into the viewport and get hit result on the floor. Just look there, and here is a documentation:
https://docs.unrealengine.com/latest/INT/API/Runtime/Engine/GameFramework/APlayerController/GetHitResultUnderCursor/index.html

If you just deproject cursor coordinates you get a 3D location at the depth of the screen (the camera). You have to use that location and direction to perform a raytrace. Or, like I said in my earlier answer, you simply call GetHitResultUnderCursor() on the player-controller, which does this for you internally.

edit: or if there’s no geometry to raytrace against, you can just take the deprojected location and add the deprojected direction or camera-forward vector (whichever you prefer) multiplied by a distance scalar.

Okay, I did that and it worked, but now the sprite gets scaled up every tick

//Sets the location of Longpakt's head to the mouse.
void ALongpakt::SetLocation()
{
 FHitResult Hit;
 APlayerController* MyController = GetWorld()->GetFirstPlayerController();
 MyController->GetHitResultUnderCursor(ECC_Visibility, false, Hit);

 if (Hit.bBlockingHit)
 {
 // We hit something, move there
 Body->SetWorldLocation(Hit.Location);
  }
 }

If your sprite gets scaled up, it’s an unrelated problem, because nothing in that small code section would be able to do that.

I can’t possibly know the cause without more information, but I would start looking into parent/child-relationships (attachments) of your actors and components and check how scale vectors are being “inherited”.

Okay, so what I did is I changed the camera to orthographic, and that seemed to solve it.