- Home /
Difficulties with world space canvas interaction
I've been trying to setup my menus to be within a world space canvas for a while now. It's an FPS game and I've properly locked all movement while in the inventory and enabled mouse movement but I've had numerous issues actually getting it working.
My latest attempt has produced a new set of issues that has me and the people helping me stumped. I am trying to get a custom mouse pointer image to follow the mouse position in the menu.
Here is the latest batch of code, placed on the mouse pointer's 3d image as a child of the canvas, which is a child of the PDA object.
using UnityEngine;
public class PDAMouse : MonoBehaviour
{
public RectTransform PDAMouseImage;
public Vector3 offset;
public GameObject PlayerPDA;
public Camera cam;
void Update()
{
MoveObject();
}
public void MoveObject()
{
Vector3 pos = Input.mousePosition + offset;
Collider pdaCollider = PlayerPDA.GetComponent<MeshCollider>();
Ray mouseRay = cam.ScreenPointToRay(Input.mousePosition);
Vector3 targetPos = Vector3.zero; // the position that the pointer will default to if ther raycast doesn't hit
if (pdaCollider.Raycast(mouseRay, out RaycastHit hit, float.PositiveInfinity))
{
targetPos = hit.point;
}
PDAMouseImage.position = cam.WorldToScreenPoint(targetPos);
}
}
The latest issue has the mouse gameobject, for whatever reason, be well out of bounds of the entire map even though it seems to be follow mouse movements. Here's a video of the issue (the game object is selected, and is the object you see moving on the top screen)
https://www.dropbox.com/s/c1zn1792555o1nb/s3x2411bQw.mp4?dl=0
And an image of the canvas on the PDA, so you can see it's slotted in and sized fine, along with the mouse image in its starting position:
https://i.imgur.com/yWwNSDq.png
I would be extremely appreciative for any help here.
Answer by misher · Oct 10, 2019 at 08:31 AM
First of all check if your world canvas has a collider on it, you can add simple box collider to it if not, make sure it extends the whole desired area of your UI. Now raycast code should be more like this:
public void MoveObject()
{
// ray from mouse position on the screen to the world
Ray mouseRay = cam.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(mouseRay, out RaycastHit hit))
{
// move the cursor game object to the hit position in the world space + offset
PDAMouseImage.position = hit.point;
PDAMouseImage.localPosition += offset;
// make sure to set corectly the forward axis of your cursor object or you can inverse it with minus
PDAMouseImage.forward = hit.normal;
}
}
Fantastique! That got me further than anything else, thank you.
$$anonymous$$y new problems are twofold, and only one I think I can probably get an answer for elsewhere.
The image follows the mouse but it jitters and lags behind a bit.
Is there a good method to lock the image into the bounds of the canvas?
This could be related to rotation i think, you can ignore the part of making cursor match hit.normal, or make it match the forward of the parent transform (in the canvas structure or the canvas itself). For the position, you can try to apply some smoothing algorithm to avoid drastic spontaneous shifting during some "bad" frames.
Having your cursor recttransform's dimension and pivot, and the also same data of the parent recttransform where you wan to bound it, you can check if your cursor is indeed within the parent bounds and so calculate and apply a translation to make it stay inside. $$anonymous$$ore simler would be to set the local position clamping the possible values, something like
cursorTransform.localPosition = new Vector3($$anonymous$$athf.Clamp(currentLocalX, 0, parentWidth - cursorWidth), $$anonymous$$athf.Clamp(currentLocalY, 0, parentHeight - cursorHeight), 0);
I Also think you should better handle the offset with pivot.