Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Resolved Mouse Position in 3D World Space Looses Alignment When Camera Rotates

Discussion in 'Scripting' started by WMKertz, May 10, 2021.

  1. WMKertz

    WMKertz

    Joined:
    Apr 28, 2021
    Posts:
    5
    Hi there. I'm trying to build a control scheme where a player uses the mouse to interact with objects in 3D scenes. They can pick up objects, move them, drop them, activate them, ect. The backbone of this is converting from screen space to world space, using ScreenPointToRay to set the Z position from the camera. This works so long as the camera remains perpendicular to the Z axis, but the camera is intended to move and rotate. When the camera is rotated the cursor quickly looses z alignment.

    I'm pretty sure what I need is a way of returning the raycast hit.point.z in some local space with the camera which can then be converted back to world space. Unfortunately every search I've made for a solution has only returned variations of what I'm already working with.

    Here's the relevant parts of the script.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Player : MonoBehaviour
    6. {
    7.     [Header("Player")]
    8.     public Camera mainCamera;
    9.     public Vector3 mouseWorldPoint;
    10.     [SerializeField] public int playerLayer = 3;
    11.     [SerializeField] private float mouseDepth = 60f;
    12.     [SerializeField] public GameObject cursor;
    13.  
    14.    void Start()
    15.     {
    16.         cursor = GameObject.Find("Cursor");
    17.         mainCamera = Camera.main;
    18.     }
    19.  
    20.     void Update()
    21.     {
    22.         //Cursor in 3D world space
    23.         mouseWorldPoint = GetMouseAsWorldPoint();
    24.         cursor.transform.position = mouseWorldPoint;
    25.     }
    26.  
    27.     public Vector3 GetMouseAsWorldPoint()
    28.     {
    29.         //Raycast from camera through screen point to hitpoint
    30.         Ray mouseRay = mainCamera.ScreenPointToRay(Input.mousePosition);
    31.         RaycastHit mouseHit;
    32.      
    33.         var layerMask = ~(1 << playerLayer);
    34.  
    35.         Physics.Raycast(mouseRay, out mouseHit, mouseDepth, layerMask);
    36.  
    37.         //Convert mouse position
    38.         Vector3 mousePoint = Input.mousePosition;
    39.  
    40.         mousePoint.z = mouseHit.point.z - mainCamera.transform.position.z;
    41.      
    42.         return mainCamera.ScreenToWorldPoint(mousePoint);
    43.     }
    44. }
     
    unity_H67ysrvcXsKLHw likes this.
  2. WMKertz

    WMKertz

    Joined:
    Apr 28, 2021
    Posts:
    5
    Wouldn't you know, after a day of considering asking for help, 5 minutes after posting this I figured out a solution. For anyone else who encounters a similar issue here's the fix:
    Code (CSharp):
    1. mousePoint.z = mainCamera.transform.InverseTransformPoint(mouseHit.point).z;
     
    xjjon likes this.