I had bought an asset earlier this month, ‘Scratch It’, on the Unity store however the asset did not work as a few comments had mentioned. I downloaded an old version of Unity, V4.3, as that was the version it was created with and it almost worked, but still not really. I don’t have a lot of experience with these functions so I’m not sure where the problem is. The demo scene that the asset came with had this script attached to a quad object, with a read/write enabled material on it (using the shader Legacy/Transparent/Vertex lit)
The scratch script:
using UnityEngine;
using System.Collections;
public enum RefreshRate
{
_10_FPS = 10,
_20_FPS = 20,
_30_FPS = 30,
_40_FPS = 40,
_50_FPS = 50,
_60_FPS = 60,
}
public class ScratchIt : MonoBehaviour
{
public bool interpolateMovement = true;
public int brushSize = 30;
public RefreshRate refreshRate = RefreshRate._30_FPS;
[SerializeField, Range(10, 500)] int maxCycleByInterpolation = 100;
[SerializeField, Range(1, 10)] int alphaCheckPrecision = 5;
[SerializeField] float scratchCompleted;
public float ScratchCompleted
{
get {return scratchCompleted;}
}
Color[] brush;
Color32[] data;
Texture2D tex;
float timer;
Vector2 oldPosition;
RenderTexture rt;
Texture2D current;
void Start ()
{
oldPosition = Vector2.zero;
timer = 0;
current = GetComponent<Renderer>().material.GetTexture("_MainTex") as Texture2D;
ResetCovering();
int tabSize = current.width * current.height;
brush = new Color[tabSize];
for (int i = 0; i < tabSize; i++)
brush[i] = new Color(0, 0, 0, 0);
}
/// <summary>
/// Resets the covering. The image goes back to it's original texture
/// </summary>
public void ResetCovering()
{
data = current.GetPixels32();
Texture2D newTex = new Texture2D(current.width, current.height);
newTex.SetPixels32(data);
GetComponent<Renderer>().material.SetTexture(0, newTex);
tex = newTex;
tex.Apply();
updatePercentage();
}
void Update ()
{
timer += Time.deltaTime;
if (Input.GetMouseButton(0))
{
Ray r = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
Physics.Raycast(r, out hit);
try
{
if (hit.collider.gameObject == this.gameObject)
{
if (!interpolateMovement)
scratch(new Vector2(hit.textureCoord.x * tex.width, hit.textureCoord.y * tex.height));
if (timer > (1f / (float)refreshRate))
{
if (interpolateMovement)
scratch(new Vector2(hit.textureCoord.x * tex.width, hit.textureCoord.y * tex.height));
updatePercentage();
tex.Apply();
timer = 0;
}
}
}
catch {
}
}
}
/// <summary>
/// Updates the percentage of scratching completed.
/// It's based of the amount of transparent pixels into the image.
/// equation: sum(each pixel alpha) / number of pixels
/// </summary>
public void updatePercentage()
{
Color32[] tmp = tex.GetPixels32(); // __________ SLOW __________
float value = 0;
for (int i = 0; i < tmp.Length; i += alphaCheckPrecision)
value += tmp[i].a;
scratchCompleted = 1 - value / (255 * data.Length / 5);
}
void scratchInterpolated(Vector2 position)
{
if (Input.GetMouseButtonDown(0))
oldPosition = position;
int i = 0;
Vector2 tmpPos = oldPosition;
Vector2 dir = (position - tmpPos).normalized;
if (Vector2.Distance(tmpPos, position) > maxCycleByInterpolation)
{
oldPosition = position;
Debug.Log("The interpolation is taking too much cycles");
}
else while (Vector2.Distance(tmpPos, position) > 2)
{
oldPosition = position;
scratchPoint(tmpPos);
tmpPos += dir;
i++;
if (i > maxCycleByInterpolation)
{
Debug.Log("The interpolation is taking too much cycles");
break;
}
}
}
/// <summary>
/// Scratchs a single point.
/// </summary>
/// <param name="position">Position, x:y on the texture</param>
public void scratchPoint(Vector2 position)
{
Vector2 tmpPos = position - new Vector2(brushSize / 2, brushSize / 2);
Vector2 cl = new Vector2((tmpPos.x + brushSize) - tex.width,
(tmpPos.y + brushSize) - tex.height);
tmpPos = new Vector2(Mathf.Clamp(tmpPos.x, 0f, tmpPos.x),
Mathf.Clamp(tmpPos.y, 0f, tmpPos.y));
Vector2 tmpBrushSize = new Vector2(Mathf.Clamp(brushSize, 0, brushSize - cl.x + 1),
Mathf.Clamp(brushSize, 0, brushSize - cl.y + 1));
if (tmpPos.x <= 0)
tmpBrushSize.x = position.x + brushSize / 2;
if (tmpPos.y <= 0)
tmpBrushSize.y = position.y + brushSize / 2;
tex.SetPixels((int)tmpPos.x, (int)tmpPos.y, (int)tmpBrushSize.x, (int)tmpBrushSize.y, brush, 0);
}
/// <summary>
/// Scratchs main method. be careful, This method will scratch with interpolation if it's activated
/// See the "interpolate" attribute
/// </summary>
/// <param name="position">Position, x:y on the texture</param>
public void scratch(Vector2 position)
{
if (interpolateMovement)
scratchInterpolated(position);
else
scratchPoint(position);
}
/// <summary>
/// Scratchs main method. be careful, This method will scratch with interpolation if it's activated
/// See the "interpolate" attribute
/// </summary>
/// <param name="position">Position, x:y on the texture</param>
public void scratch(Vector3 position)
{
scratch(new Vector2((int)position.x, (int)position.y));
}
}
I really want to make this work but I’ve spent hours on it with no results.