- Home /
Make character look at mouse position, not world position
Hello, I want my character to always face the mouse position. This is a isometric type game.
This is how i've done it now, in the Update function:
//aiming
var ray = Camera.main.ScreenPointToRay (Input.mousePosition);
var hit : RaycastHit;
if (Physics.Raycast (ray,hit,1000)) {
Debug.DrawLine (ray.origin, hit.point,Color.green);
aimPos = Vector3(hit.point.x,upperBody.position.y,hit.point.z);
}
upperBody.LookAt(aimPos);
This sort of works, however. The character will look at objects sticking up out of the ground, as the camera ray hit's them. This results in the player not being able to look parallel to a wall for example, since they will either look AT the wall, or at the ground beside it.
I know that I can put the objects that I don't want the ray to collide with on an IgnoreRayCast layer, however, that creates another problem. If the character climbs up on a wall, and that wall is on ignore raycast, if the cursor is put below the character, it will still look up (away from the camera), since the ray from the camera passes through the wall that the character is standing on, and lands in front of the character.
What I want is basically: Whenever the cursor is below the character, it is supposed to look down. When it is above the character, it is supposed to look up, same things goes for left and right.
Could anyone please point me in the right direction?
Thanks. /Alex
EDIT: Below is a screenshot of the issue. As you can see, the mouse cursor is below the character, but it doesn't look towards the mouse, since the ray shoots through the object that the character is standing on. The objects need to ignore the raycast, since I always want the character to look at the mouse position, not at the objects. (The legs rotate independently of the upper body, they are irrelevant to this issue)
Could you possible flip how you're doing your calculations. Ins$$anonymous$$d of going from screen to world, go from world to screen. Something like the following:
Vector3 upperBodyScreenPos = Camera.main.WorldToScreenPoint(upperBody.position);
Vector3 upperBodyToCursor = Input.mousePosition - upperBodyScreenPos;
upperBody.rotation = Quaternion.LookRotation(upperBodyToCursor, Vector3.Up);
I'm not sure if this exact code would work, but maybe someone could extend upon the idea.
Your description is quite confusing. Could you make some pictures to explain what you mean and how it should work?
Thanks jkpenner, I tried your method, it seems logical. However, the character looked up in the sky, and didn't face the mouse cursor correctly. I tried setting upperBodyToCursor.y = 0; , but it still didn't look correctly at the mouse cursor. I can't seem to figure out why...
Answer by alexanderflink · Oct 21, 2014 at 10:56 AM
Hello! I managed to get it right, this is how I did it. Thanks cmonroy and jkpenner for explaining how the logic should be. Note how I use upperBodyToCursor.y instead of z, since z is the distance from the camera, not direction to mouse cursor.
//aiming
//get the screen position of the upper body bone
upperBodyScreenPos = Camera.main.WorldToScreenPoint(upperBody.position);
//get the direction from the upper body to cursor
upperBodyToCursor = Input.mousePosition - upperBodyScreenPos;
//set aimPos to upperbody position + direction vector
aimPos = (upperBody.position + Vector3(upperBodyToCursor.x,upperBody.position.y,upperBodyToCursor.y));
// transform aimPos to camera space
finalAimPos = cameraDirTransform.TransformDirection(Vector3(aimPos.x,0,aimPos.z));
//look at aimpos
upperBody.LookAt(finalAimPos);
//calculate movement relative to camera
finalMovement = cameraDirTransform.TransformDirection(Vector3(horizontalInput,0,verticalInput));
Answer by Christian.Tucker · Oct 17, 2014 at 09:04 AM
Use WorldToScreenPoint instead of ScreenPointToRay
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f));
RaycastHit hit;
Vector3 direction;
Quaternion rotation;
if(Physics.Raycast (ray, out hit, 5f))
{
direction = (hit.point - transform.position).normalized;
}
else
{
direction = ray.direction;
}
rotation = Quaternion.FromToRotation(transform.forward, direction);
This will shoot a raycast out from the center of your screen, it will then perform calculations to get the center of the screen if it hits something, and if it doesn't it will simply turn towards the direction of the ray.
Thank you for you answer, i'm not sure im following though. I can't see any "WorldToScreenPoint" function in your code?
Also, this creates a ray from the center of the viewport, not from the mouse position. How would I go about shooting a ray from the mouse position this way? Thanks!
Answer by cmonroy · Oct 18, 2014 at 10:04 AM
The origin of the ray should be located at your character's location. The mouse position should be the end destination of the ray. The problem as I see it is that even though you have a definite X and Y values, the required Z (depth) is estimated for any geometry available at that spot and may not always be what you expect.
You could, however, create an invisible object at a fixed distance from your character (let's say 2 meters) and provide the X and Y values from your Mouse position. Having the X, Y and Z components, just transform the position of the target and simply look at it.