Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Seal_I · Jan 05, 2014 at 11:53 AM · 2dspritecolorgetpixelstexturecoord

How to get "pixel" color for Sprite (U4.3)?

Task: need to get sprites's color after click on it.

In 3D it was done using RaycastHit -> textureCoord -> texture.GetPixel (like this http://answers.unity3d.com/questions/545519/best-way-to-click-on-a-object-behind-other.html, but reinvented own wheel)))

But in unity sprites (U4.3) RaycastHit2D has no textureCoord at all. Is there any was to get coordinates or something else that can help to get "pixel's" color?

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image upupzealot · Mar 25, 2014 at 05:26 PM 0
Share

Same problem. Anybody help?

avatar image Dblfstr · Mar 25, 2014 at 05:39 PM 0
Share

Why cant you use RaycastHit?

avatar image SirGive · Mar 25, 2014 at 05:41 PM 0
Share

We had to end up using 3d colliders for our 2d game, you may have to do that too. It seems unity forgot a ton of stuff for 2d

avatar image joshpsawyer · Mar 28, 2014 at 08:00 PM 0
Share

RaycastHit2D.point is a Vector2 that represents where the collision occured, and Texture2D has the function GetPixel(). Not sure how you'd pull them together, but it seems like the right direction

2 Replies

· Add your reply
  • Sort: 
avatar image
2

Answer by Anxo · Jul 17, 2014 at 09:23 PM

Concept: Grab a sprite, grab the texture of the sprite, scan the texture.

But first, change your import settings to Advanced and enable read and write.

Execution:

 private Texture2D myTexture;
 private Sprite mySprite;
 
 void Start(){
 mySprite = gameObject.GetComponent<SpriteRenderer>().sprite;
 myTexture = mySprite.texture;
 Color MyPixel = myTexture.GetPixel(x,y);
 
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image robertbu · Jul 17, 2014 at 10:00 PM 1
Share

@Anxo - good start, but you only get them part of the way there. First, only part of the sprite texture may be mapped into the sprite. See Sprite.rect. In addition, you still need to figure out how to map a mouse/hit position in world coordinates to the pixel you need to grab.

avatar image keithadler · Feb 05, 2015 at 07:37 AM 0
Share

Can someone please provide a full answer for this?

avatar image
2

Answer by guavaman · Apr 29, 2015 at 10:35 PM

This will get a pixel's color from a Sprite's texture without using colliders. This is based on casting a ray from a mouse position to get the pixel's color. Note that this gets the texture's color, not the color as processed by the material's shaders. It also requires that your texture have the Read/Write option enabled in the inspector settings or it will throw an error. It works in 2D orthographic and 3D perspective.

(This was adapted from a sprite selector I just wrote that uses the same technique to select the sprite by clicking on any opaque pixel in the sprite, ignoring transparent pixels.)

Note: This will not work on PVRTC texture compression because texture.GetPixel is not supported.

 public bool GetSpritePixelColorUnderMousePointer(SpriteRenderer spriteRenderer, out Color color) {
     color = new Color();
     Camera cam = Camera.main;

     Vector2 mousePos = Input.mousePosition;
     Vector2 viewportPos = cam.ScreenToViewportPoint(mousePos);

     if(viewportPos.x < 0.0f || viewportPos.x > 1.0f || viewportPos.y < 0.0f || viewportPos.y > 1.0f) return false; // out of viewport bounds

     // Cast a ray from viewport point into world
     Ray ray = cam.ViewportPointToRay(viewportPos);
     
     // Check for intersection with sprite and get the color
     return IntersectsSprite(spriteRenderer, ray, out color);
 }

 private bool IntersectsSprite(SpriteRenderer spriteRenderer, Ray ray, out Color color) {
     color = new Color();
     if(spriteRenderer == null) return false;

     Sprite sprite = spriteRenderer.sprite;
     if(sprite == null) return false;

     Texture2D texture = sprite.texture;
     if(texture == null) return false;

     // Check atlas packing mode
     if(sprite.packed && sprite.packingMode == SpritePackingMode.Tight) {
         // Cannot use textureRect on tightly packed sprites
         Debug.LogError("SpritePackingMode.Tight atlas packing is not supported!");
         // TODO: support tightly packed sprites
         return false;
     }

     // Craete a plane so it has the same orientation as the sprite transform
     Plane plane = new Plane(transform.forward, transform.position);

     // Intersect the ray and the plane
     float rayIntersectDist; // the distance from the ray origin to the intersection point
     if(!plane.Raycast(ray, out rayIntersectDist)) return false; // no intersection

     // Convert world position to sprite position

     // worldToLocalMatrix.MultiplyPoint3x4 returns a value from based on the texture dimensions (+/- half texDimension / pixelsPerUnit) )
     // 0, 0 corresponds to the center of the TEXTURE ITSELF, not the center of the trimmed sprite textureRect
     Vector3 spritePos = spriteRenderer.worldToLocalMatrix.MultiplyPoint3x4(ray.origin + (ray.direction * rayIntersectDist));

     Rect textureRect = sprite.textureRect;

     float pixelsPerUnit = sprite.pixelsPerUnit;
     float halfRealTexWidth = texture.width * 0.5f; // use the real texture width here because center is based on this -- probably won't work right for atlases
     float halfRealTexHeight = texture.height * 0.5f;

     // Convert to pixel position, offsetting so 0,0 is in lower left instead of center
     int texPosX = (int)(spritePos.x * pixelsPerUnit + halfRealTexWidth);
     int texPosY = (int)(spritePos.y * pixelsPerUnit + halfRealTexHeight);

     // Check if pixel is within texture
     if(texPosX < 0 || texPosX < textureRect.x || texPosX >= Mathf.FloorToInt(textureRect.xMax)) return false; // out of bounds
     if(texPosY < 0 || texPosY < textureRect.y || texPosY >= Mathf.FloorToInt(textureRect.yMax)) return false; // out of bounds

     // Get pixel color
     color = texture.GetPixel(texPosX, texPosY);

     return true;
 }
Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image McTesla · Jan 27, 2016 at 03:18 PM 1
Share

Hey, thanks for this awesome piece of code. I used this to check if the mouse is over a sprite by checking if alpha value > a certain threshold.

One thing I noticed was that this implementation didn't work when using sprite-sheets (Sprite Type "$$anonymous$$ultiple" in the Texture Settings). Luckily there is an easy fix:

 Rect textureRect = sprite.textureRect;
 float pixelsPerUnit = sprite.pixelsPerUnit;
 float halfRealTexWidth = sprite.rect.width * 0.5f;
 float halfRealTexHeight = sprite.rect.height * 0.5f;

 int texPosX = (int)(sprite.rect.x + (spritePos.x * pixelsPerUnit + halfRealTexWidth));
 int texPosY = (int)(sprite.rect.y + (spritePos.y * pixelsPerUnit + halfRealTexHeight));

 // Check if pixel is within texture
 if(texPosX < 0 || texPosX < textureRect.x || texPosX >= $$anonymous$$athf.FloorToInt(textureRect.x$$anonymous$$ax)) return false;
 if(texPosY < 0 || texPosY < textureRect.y || texPosY >= $$anonymous$$athf.FloorToInt(textureRect.y$$anonymous$$ax)) return false;
avatar image vrivotti · Dec 10, 2018 at 12:52 PM 1
Share

Thanks for this code.

If someone finds this answer, like I did, and needs to adapt to use with sprite atlas with custom pivots, just replace these lines:

 int texPosX = (int)(spritePos.x * pixelsPerUnit + sprite.rect.x + sprite.pivot.x);
 int texPosY = (int)(spritePos.y * pixelsPerUnit + sprite.rect.y + sprite.pivot.y);
 
 // Check if pixel is within texture
 if (texPosX < 0 || texPosX < sprite.rect.x || texPosX >= $$anonymous$$athf.FloorToInt(sprite.rect.x$$anonymous$$ax)) return false;
             
 if (texPosY < 0 || texPosY < sprite.rect.y || texPosY >= $$anonymous$$athf.FloorToInt(sprite.rect.y$$anonymous$$ax)) return false;
 

avatar image Fireal1983 · Jul 09, 2020 at 01:30 PM -1
Share

This code is brilliant and I while I understand it I don't know how to implement or 'call' it.

Can anyone explain what I would pass in for the SpriteRenderer and Color params?

The method finds the color at the desired pixel and returns the value through an 'out' param, but since I don't know any color information yet, how do I pass anything in?

Also why is the methods return type set to a bool?

Would really appreciate any help or maybe I'm missing something on how 'out' works.

Thanks.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

29 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

renderer.enabled doesn't work but coloring does 1 Answer

Incorrect Sprite Color on Android build 0 Answers

Change dynamicaly a PNG used in a motion 1 Answer

Sprite color changes after import 1 Answer

pixels shown in game view that are not there in the scene 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges