Author Topic: Raycast hit position on sprite  (Read 4975 times)

kittikun

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 5
  • Posts: 46
    • View Profile
Raycast hit position on sprite
« on: March 05, 2014, 08:58:38 AM »
Hi,

I currently need to find which sprite was hit when for example I have two sprites on top of each other and the top one had a transparent empty area.

I want to point out that this post is not working in my case
http://www.tasharen.com/forum/index.php?topic=7824.0

Probably because my sprites are positionned in the world 3D. Here is my current setup:

UIRoot (3D) fixed size, 640

I am currently using the current code to achieve hit detection

  1.         void Update()
  2.         {
  3.                 if (!Input.GetMouseButton(0))
  4.                         return;
  5.                
  6.                 RaycastHit hit;
  7.                 if (!Physics.Raycast(UICamera.mainCamera.camera.ScreenPointToRay(Input.mousePosition), out hit))
  8.                         return;
  9.                
  10.                 UISprite sprite = hit.transform.GetComponent<UISprite>();
  11.                 Vector3 localHit = hit.transform.InverseTransformPoint(hit.point);
  12.  
  13.  
  14.                 Debug.Log(string.Format("World {0}", hit.point));
  15.                 Debug.Log(string.Format("Local {0}", localHit));
  16.  
  17.  
  18.                 if (sprite == null)
  19.                         return;
  20.                
  21.                 Texture2D tex = sprite.mainTexture as Texture2D;
  22.                 UISpriteData data = sprite.atlas.GetSprite(sprite.spriteName);
  23.  
  24.                 Debug.Log(string.Format("data {0} {1} {2} {3}", data.x, data.y, data.width, data.height));
  25.                 Bounds bounds = sprite.CalculateBounds();
  26.                 Debug.Log(string.Format("Bounds min {0}", bounds.min));
  27.                 Debug.Log(string.Format("Bounds size {0}", bounds.size));
  28.  
  29.                 Vector2 hitLocalUV = Vector2.zero;
  30.  
  31.                 // normalize
  32.                 if (bounds.size.x > 0)
  33.                         hitLocalUV.x = (localHit.x - bounds.min.x) / (bounds.size.x);
  34.  
  35.                 if (bounds.size.y > 0)
  36.                         hitLocalUV.y = (localHit.y - bounds.min.y) / (bounds.size.y);
  37.  
  38.                 Debug.Log(string.Format("hitLocalUV {0}", hitLocalUV));
  39.  
  40.                 Texture altasTex = sprite.atlas.texture;
  41.  
  42.                 // use scale to to (a.x * b.x) + (a.y * b.y)...
  43.                 Vector2 hitLocalPixel = hitLocalUV;
  44.                 hitLocalPixel.Scale(new Vector2(data.width, data.height));
  45.                 Debug.Log(string.Format("hitLocalPixel {0}", hitLocalPixel));
  46.  
  47.                 Vector2 hitAtlasPixel = hitLocalPixel + new Vector2(data.x, data.y);
  48.                 Debug.Log(string.Format("hitAtlasPixel {0}", hitAtlasPixel));
  49.  
  50.                 Color hitPixel = tex.GetPixel(Mathf.RoundToInt(hitAtlasPixel.x), Mathf.RoundToInt(hitAtlasPixel.y));
  51.  
  52.  
  53.                 Debug.Log(string.Format("hitPixel {0}", hitPixel));
  54.         }
  55.  

if I click on a point that should be (348, 1200) on the atlas, I get (348, 1020) for hitAtlasPixel
There only seems to be discrepancy on Y so I was wondering if fixed size could have something to do about it but

root.pixelSizeAdjustment = 1.319588 so the ratio doesn't seem to match my problem

I feel like I am so close of it but i cannot figure it out!

It would be great if you had some tips to give

Thanks you

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Raycast hit position on sprite
« Reply #1 on: March 05, 2014, 09:07:48 AM »
Mouse position and screen space are inverted, aren't they? You need to flip the mouse Y (Screen.height - y).

kittikun

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 5
  • Posts: 46
    • View Profile
Re: Raycast hit position on sprite
« Reply #2 on: March 06, 2014, 04:08:48 AM »
That doesn't seem to be it, could it be that UISpriteData (0,0) is top-left ?

kittikun

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 5
  • Posts: 46
    • View Profile
Re: Raycast hit position on sprite
« Reply #3 on: March 06, 2014, 04:26:38 AM »
Looks like it is, so If I change

  1.  Vector2 hitAtlasPixel = hitLocalPixel + new Vector2(data.x, data.y);

to

  1.                 Vector2 hitAtlasPixel = new Vector2(hitLocalPixel.x, sprite.atlas.texture.height - data.y - data.height + hitLocalPixel.y);
  2.  

Everything is working fine!