SetPixels not working?

Hey, I’m trying to render pixels to a raw image in the canvas by creating an array of Color32s as a buffer then send them to a texture2d. Yeah this is a weird thing to do with Unity but I thought it’d be fun to try, problem is I can’t seem to get anything to actually render to the screen. For whatever reason it just sets the image to a weird transparent gray, I’m wondering if there’s anything I’m doing wrong? Here is my code

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Raycaster : MonoBehaviour
{
    public int ScreenWidth = 320;
    public int ScreenHeight = 180;

    double posX = 22, posY = 12;  //x and y start position
    double dirX = -1, dirY = 0; //initial direction vector
    double planeX = 0, planeY = 0.66; //the 2d raycaster version of camera plane

    Color32[] buffer;
    public Texture2D[] texture;
    public RawImage Screen;

    int[,] worldMap;

    // Use this for initialization
    void Start()
    {

        buffer = new Color32[ScreenWidth * ScreenHeight];

        worldMap = new int[,]
        {
            { 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,7,7,7,7,7,7,7,7},
            { 4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
            { 4,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
            { 4,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7},
            { 4,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,7},
            { 4,0,4,0,0,0,0,5,5,5,5,5,5,5,5,5,7,7,0,7,7,7,7,7},
            { 4,0,5,0,0,0,0,5,0,5,0,5,0,5,0,5,7,0,0,0,7,7,7,1},
            { 4,0,6,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
            { 4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,7,7,1},
            { 4,0,8,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,0,0,0,8},
            { 4,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,7,0,0,0,7,7,7,1},
            { 4,0,0,0,0,0,0,5,5,5,5,0,5,5,5,5,7,7,7,7,7,7,7,1},
            { 6,6,6,6,6,6,6,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
            { 8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4},
            { 6,6,6,6,6,6,0,6,6,6,6,0,6,6,6,6,6,6,6,6,6,6,6,6},
            { 4,4,4,4,4,4,0,4,4,4,6,0,6,2,2,2,2,2,2,2,3,3,3,3},
            { 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
            { 4,0,0,0,0,0,0,0,0,0,0,0,6,2,0,0,5,0,0,2,0,0,0,2},
            { 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
            { 4,0,6,0,6,0,0,0,0,4,6,0,0,0,0,0,5,0,0,0,0,0,0,2},
            { 4,0,0,5,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,2,0,2,2},
            { 4,0,6,0,6,0,0,0,0,4,6,0,6,2,0,0,5,0,0,2,0,0,0,2},
            { 4,0,0,0,0,0,0,0,0,4,6,0,6,2,0,0,0,0,0,2,0,0,0,2},
            { 4,4,4,4,4,4,4,4,4,4,1,1,1,2,2,2,2,2,2,3,3,3,3,3}
        };
    }

    // Update is called once per frame
    void Update()
    {
        for (int x = 0; x < ScreenWidth; x++)
        {
            //calculate ray position and direction
            double cameraX = 2 * x / (double)ScreenWidth - 1; //x-coordinate in camera space
            double rayDirX = dirX + planeX * cameraX;
            double rayDirY = dirY + planeY * cameraX;

            //which box of the map we're in
            int mapX = (int)posX;
            int mapY = (int)posY;

            //length of ray from current position to next x or y-side
            double sideDistX;
            double sideDistY;

            //length of ray from one x or y-side to next x or y-side
            double deltaDistX = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX));
            double deltaDistY = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY));
            double perpWallDist;

            //what direction to step in x or y-direction (either +1 or -1)
            int stepX;
            int stepY;

            int hit = 0; //was there a wall hit?
            int side = 0; //was a NS or a EW wall hit?

            //calculate step and initial sideDist
            if (rayDirX < 0)
            {
                stepX = -1;
                sideDistX = (posX - mapX) * deltaDistX;
            }
            else
            {
                stepX = 1;
                sideDistX = (mapX + 1.0 - posX) * deltaDistX;
            }
            if (rayDirY < 0)
            {
                stepY = -1;
                sideDistY = (posY - mapY) * deltaDistY;
            }
            else
            {
                stepY = 1;
                sideDistY = (mapY + 1.0 - posY) * deltaDistY;
            }

            //perform DDA
            while (hit == 0)
            {
                //jump to next map square, OR in x-direction, OR in y-direction
                if (sideDistX < sideDistY)
                {
                    sideDistX += deltaDistX;
                    mapX += stepX;
                    side = 0;
                }
                else
                {
                    sideDistY += deltaDistY;
                    mapY += stepY;
                    side = 1;
                }
                //Check if ray has hit a wall
                if (worldMap[mapX, mapY] > 0) hit = 1;
            }

            //Calculate distance of perpendicular ray (Euclidean distance will give fisheye effect!)
            if (side == 0) perpWallDist = (mapX - posX + (1 - stepX) / 2) / rayDirX;
            else perpWallDist = (mapY - posY + (1 - stepY) / 2) / rayDirY;

            //Calculate height of line to draw on screen
            int lineHeight = (int)(ScreenHeight / perpWallDist);

            //calculate lowest and highest pixel to fill in current stripe
            int drawStart = -lineHeight / 2 + ScreenHeight / 2;
            if (drawStart < 0) drawStart = 0;
            int drawEnd = lineHeight / 2 + ScreenHeight / 2;
            if (drawEnd >= ScreenHeight) drawEnd = ScreenHeight - 1;

            //texturing calculations
            int texNum = worldMap[mapX, mapY] - 1; //1 subtracted from it so that texture 0 can be used!

            int texWidth = texture[texNum].width;
            int texHeight = texture[texNum].height;

            //calculate value of wallX
            double wallX; //where exactly the wall was hit
            if (side == 0) wallX = posY + perpWallDist * rayDirY;
            else wallX = posX + perpWallDist * rayDirX;
            wallX -= Math.Floor((wallX));

            //x coordinate on the texture
            int texX = (int)(wallX * (double)(texWidth));
            if (side == 0 && rayDirX > 0) texX = texWidth - texX - 1;
            if (side == 1 && rayDirY < 0) texX = texWidth - texX - 1;

            for (int y = drawStart; y < drawEnd; y++)
            {
                int d = y * 256 - ScreenHeight * 128 + lineHeight * 128;  //256 and 128 factors to avoid floats
                                                                          // TODO: avoid the division to speed this up
                int texY = ((d * texHeight) / lineHeight) / 256;
                Color32 color = (Color32)texture[texNum].GetPixel(texX, texY);
                //make color darker for y-sides: R, G and B byte each divided through two with a "shift" and an "and"
                if (side == 1)
                {
                    color.r /= 2;
                    color.g /= 2;
                    color.b /= 2;
                }
                buffer[ScreenHeight * y + x] = color;
            }
        }
        DrawBuffer();
        for (int x = 0; x < ScreenWidth; x++) for (int y = 0; y < ScreenHeight; y++) buffer[y * x] = Color.black; //clear the buffer


    }

    void DrawBuffer()
    {
        Texture2D screen = new Texture2D(ScreenWidth, ScreenHeight);
        Screen.texture = screen;

        screen.SetPixels32(buffer);
    }
}

Is anyone able to shed any light on this for me?

I was having the exact same problem. Turns out you need to call Apply() on the Texture2D once you are done setting pixels. According to the documentation, it’s an expensive call so that’s why they don’t do it automatically.

Reference: Unity - Scripting API: Texture2D.SetPixel