Hi,
I’m currently trying to have a “trail” effect with a simple system of RenderTexture and Texture2D. Here is what I have:
- I have an Image with the current trails, which is a Texture2D
- I capture the elements I want a trail on on a renderTexture
- I render this on a Temp Texture2D
- I fade every pixels on my Image Texture2D
- I write above this Image the pixels of the Temp Texture2D which are not clear

It works as intended, but the performance is not too great, mainly because of the last two steps.
I tried to do it in two ways:
- A double for loop with GetPixel and SetPixel calls > 0 alloc, but far too slow.
- A double GetPixels on my temp and image Texture2D to have 2 Color I iterate on, then one final SetPixels > way faster, but allocates some MB each frame, which is clearly not acceptable (it triggers the GC.Collect very frequently, obviously).
I have spent a lot of time already looking for solutions, so I’m not sure there is one, but maybe I missed something, so here I am for help ![]()
I don’t see a good reason why the GetPixels function couldn’t have an override with a Color parameter, in order to not generate alloc (I create the array once, then the same one is always used), the same way some Physics functions work.
Here is the code if you’re curious (or if you can spot some dumb error I made):
public class RemanentCamera : MonoBehaviour
{
public UnityEngine.UI.RawImage destImage;
Camera c;
Texture2D tempTexture;
Texture2D imageTexture;
int width;
int height;
void Start ()
{
height = 256;
width = Screen.width * height / Screen.height;
c = GetComponent<Camera>();
c.targetTexture = new RenderTexture(width, height, 16);
tempTexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
imageTexture = new Texture2D(width, height, TextureFormat.ARGB32, false);
destImage.texture = imageTexture;
}
void OnDestroy()
{
c.targetTexture.Release();
}
void Update()
{
RenderTexture.active = c.targetTexture;
tempTexture.ReadPixels(new Rect(0, 0, width, height), 0, 0);
RenderTexture.active = null;
//FIRST SOLUTION
{
for(int i = 0; i < imageTexture.width; i++)
{
for(int j = 0; j < imageTexture.height; j++)
{
Color tempColor = tempTexture.GetPixel(i, j);
if(tempColor.a == 1)
{
imageTexture.SetPixel(i, j, tempColor);
}
else
{
tempColor = imageTexture.GetPixel(i, j);
if(tempColor.a > 0)
{
tempColor.a = Mathf.Max(0f, tempColor.a - Time.deltaTime * 2f);
imageTexture.SetPixel(i, j, tempColor);
}
}
}
}
}
//SECOND SOLUTION
{
Color[] tempColor = tempTexture.GetPixels();
Color[] currentColor = imageTexture.GetPixels();
for(int i = 0; i < currentColor.Length; i++)
{
if(tempColor[i].a == 1)
{
currentColor[i] = tempColor[i];
fullPixelAmount++;
}
else
{
if(currentColor[i].a > 0)
{
currentColor[i].a = Mathf.Max(0f, currentColor[i].a - Time.deltaTime * 2f);
fadePixelAmount++;
}
if(tempColor[i].a > 0)
{
currentColor[i].r = tempColor[i].a * tempColor[i].r + (1f - tempColor[i].a) * currentColor[i].r;
currentColor[i].g = tempColor[i].a * tempColor[i].g + (1f - tempColor[i].a) * currentColor[i].g;
currentColor[i].b = tempColor[i].a * tempColor[i].b + (1f - tempColor[i].a) * currentColor[i].b;
currentColor[i].a = Mathf.Min(1f, currentColor[i].a + tempColor[i].a);
blendPixelAmount++;
}
}
}
imageTexture.SetPixels(currentColor);
}
imageTexture.Apply();
}
}
I’m also open to other ways of getting the same result, it’s the only way I found.
