- Home /
What is the easiest way to convert raycasthit2D to pixel coordinates?
I have a sprite with a box collider or polygon collider and I'm looking for a calculation that will translate any raycasthit2D on that sprite into the pixel coordinates of the texture so I can use the coordinates with GetPixel().
Does anyone have some code that will do this conversion?
There are quite a few posts on similar topics but nothing that has solved my issue. Someone had suggested translating the hit into barycentric coordinates, but I'm not great with maths and it blew my mind a little bit. My project's at a standstill while I have this issue so any help will be appreciated massively :)
Thanks!
Romano
I'm sure this can be worked out (though the calculations might get a bit ugly), but I wonder if approaching the problem a bit differently might make things easier. $$anonymous$$ake a Quad a child of your sprite and size it to the same size as your sprite. Then you can do a Physics.Raycast() (i.e. 3D raycast). A RaycastHit structure gives you back the uv (RaycastHit.textureCoord) which is easy to turn into a pixel coordinate.
I also have to ask if you really need a sprite. People seem to automatically use them for 2D, but in many situations a Quad could be used ins$$anonymous$$d.
Hi there. That's an interesting suggestion, thanks. It's a 2D game full of sprites with box and polygon colliders attached. I'm already having to use 2D raycasts to detect clicks on the the collider2Ds so if possible I'd like to avoid having to do 3D raycasts too. It'd be so easy if textureCoord was included in the raycastHit2D.
I don't know much about using quads but my sprite will be animated and the quad might change size, which could start getting tricky.
Answer by fafase · Apr 15, 2014 at 05:32 AM
Considering you will hit on the edges of the sprite, you can take the position of the hit, find the local position of that hit, simply doing
LocalPos= sprite.position-hit.position
Then you can convert that local position into texture position using the width and height of it.
Uv = localPos.y/ height *textureHeight
This is considering you hit the side of it.
This is simplified but maybe you get something out of it.
EDIT: You turn the hit point to local position of the sprite. Then you do the process of conversion for both dimensions (x and y).
All you do is converting from one coordinate to another. For instance, if you have a sprite that has dimensions 2x2 at position (10,1)and you hit at position (9.5,0.5). Your texture is a 256x256.
First get the hit in sprite position:
10 - 9.5 = 0.5
1 - 0.5 = 0.5
Turn that into texture coordinates:
value * scale * textureSize
uv.x = 0.5 / 2 * 256 -> 64
uv.y = 0.5 / 2 * 256 -> 64
64,64 is the pixel position of your hit.
That looks great, I'm not sure I understand it all though. Could you explain what you mean by hitting the edges or the side of the sprite? The raycasthit2D would be a mouse click which could be anywhere within the collider.
I'm also not sure what position-hit should be replaced with in the code?
Thanks!
I think I get it, thanks. I'll try it out!
Just to make things more complicated, this wouldn't work if the sprite mode was "$$anonymous$$ultiple" would it? i.e if the sprite was animated and the texture was changing all the time.
I can't find in Animator or Animation (though there is probably one) any method returning what part of the sprite is currently used. But in the case there would not be, you can easily find which is by using the parameters you set for animation.
First you can get the current state: http://docs.unity3d.com/Documentation/ScriptReference/Animator.GetCurrentAnimatorStateInfo.html
Then you get the time https://docs.unity3d.com/Documentation/ScriptReference/AnimatorStateInfo-normalizedTime.html
it tells the fractional part is the normalized time the animation has been running.
Then you know how many sprite there is on your animation and you just do the math.
if 24 states in your animation and you are at 0.3 of the animation 0.3 * 24 = 7
you are on state 7 of your animation.
Now if your sprite sheet is 1024 width and all states are aligned:
1024/ 24 * 7 = 298
is the starting x coord. You just use the values you found previously and you add them to those and you get your uv on the whole sprite sheet.
Wow, thanks for the lengthy answer :) I thought it would be simpler to use
spriteRenderer.sprite.bounds;
OR
spriteRenderer.sprite.rect;
but so far getting nothing but 0,0,0,0 no matter what part of the texture is displaying. Am I just doing something totally wrong and could fix that or is your method the only way?
I wondered if my method could work because my animations are purely sprite based, there's no messing with position or rotation.
Your answer
Follow this Question
Related Questions
Assigning UV Map to model at runtime 0 Answers
Unity 5 uv bug? 1 Answer
Shader and Texture Scrolling depending on Direction 1 Answer
Blender to Unity strange normal import problem (bright spots) 1 Answer
Delete Uv2 of a mesh? 1 Answer