- Home /
SetPixel on a sprite texture without changing it globally
Hi, so I spent the last days experimenting with different solutions for a kind of "decal" system for my game. I found that setPixel() would probably be the best for my specific case.
The situation now is that I have a Sprite (in 3D-Space), and I want to change some Pixels on it. In order to set pixels on the sprite I had to make the texture of the sprite writable. But now everytime I set a pixel, the texture changes on all objects that use it. It even stays like that when I restart the scene.
Now this does not seem like unintended behaviour and at least kind of makes sense, but is there some way to just edit the texture on one specific object?
(And if yes, is it still feasible performance-wise?)
I don't know if its needed, but here is the code I am using. The calculation which pixel is supposed to be set is only a placeholder, I'm going to deal with that if I get SetPixel() to work
//C#
SpriteRenderer renderer = hit.collider.GetComponentInChildren<SpriteRenderer>();
Texture2D tex = renderer.sprite.texture;
Vector2 pixelUV = hit.textureCoord;
pixelUV.x *= tex.width;
pixelUV.y *= tex.height;
tex.SetPixel((int) pixelUV.x, (int) pixelUV.y, Color.black);
tex.Apply();
As Drakulo answered your question, I will only add, that I would bother more about memory consumption than performance. This will depend on your texture size and number of decals that you want to create, but you have to keep an eye on this.
And don't forget to call Compress on your texture clone, after you call Apply.
Oh, I didn't even notice there was a compress-method.
Thanks for the good advice!
Answer by Drakulo · Jan 22, 2014 at 11:08 AM
By doing this, you write the decal in your asset folder texture. That's why restarting keep it on the texture : you modified the texture file itself. You should disable the possibility to write your base texture and use a clone instead. Modifying the clone's pixels will not affect the original one.
Thanks, that was it!
I am now using this code, this seems to do what I want.
SpriteRenderer renderer = hit.collider.GetComponentInChildren<SpriteRenderer>();
Texture2D tex = renderer.sprite.texture;
//Get hit position (placeholder)
Vector2 pixelUV = hit.textureCoord;
pixelUV.x *= tex.width;
pixelUV.y *= tex.height;
//Replace texture
Texture2D newTex = new Texture2D (tex.width, tex.height, TextureFormat.ARGB32, false);
newTex.SetPixels32(tex.GetPixels32());
newTex.SetPixel((int) pixelUV.x, (int) pixelUV.y, Color.black);
newTex.Apply();
renderer.sprite = Sprite.Create(newTex, renderer.sprite.rect, new Vector2(0.5f, 0.5f));
Ins$$anonymous$$d of creating new texture and getting/setting pixels, you can use Instantiate:
Texture2D newTex = (Texture2D)GameObject.Instantiate(tex);
Yes, I agree with @ArkaneX. Apply() can be an expensive operation, use it wisely : Texture2D.Apply
Your answer
Follow this Question
Related Questions
Erasing a part of an image using SetPixel without gaps 2 Answers
How to Address Texture2D Elements from a Sprite with Sprite Mode: Multiple, in Code? 1 Answer
Painting sprite in unity 1 Answer
The name 'Joystick' does not denote a valid type ('not found') 2 Answers
Render a text on the sprite 1 Answer