I have an image, and I need to getpixel at the click location. For this to work I need to know the part of the image I clicked. I can’t do this using Input.GetMousePosition, as my image may not be the same size as the screen.
//Get the object using raycast.
//Save the mouse position when you clicked.
//Get the texture from the object.
//This will yield 3 variables:
GameObject screenObject;
Texture2D texture;
Vector2 mouseClickPosition;
//To get the pixel clicked on the texture we need the mouse position relative to the texture.
//Get the screen size
Vector2 screenSize = new Vector2(Screen.width, Screen.height);
//Get the texture size
Vector2 textureSize = new Vector2(texture.width, texture.height);
//Get the screen position of the texture (This will be the center of the image)
Vector2 textureScreenPosition = Camera.main.WorldToScreenPoint(screenObject.transform.position);
//Get the 0,0 position of the texture:
Vector2 textureStartPosition = textureScreenPosition - textureSize / 2;
//Subtract the 0,0 position of the texture from the mouse click position.
Vector2 relativeClickPosition = mouseClickPosition - textureStartPosition;
/*Simple test example*/
//Clicked at 500,500
//Example screensize of 1000,1000
//Example textureSize of 300,300
//Example texture position of 400,400
//Texture Start Position will be {400,400} - {150, 150} = {250,250}
//The relative click position = {500, 500} - {250, 250} = {250, 250}
//The texture of size 300x300 got clicked on pixel {250,250}
hmmm. if you want to paint a gameobect in your scene it might be eaiser to do a raycast with the mouse.
if you get your hit point relative to the object’s position then you can calculate from there.
using UnityEngine;
using System.Collections;
public class painer : MonoBehaviour {
public GameObject g;
public Texture2D t;
public float x,y;
void Start () {
t = new Texture2D (25, 25);
g = GameObject.CreatePrimitive (PrimitiveType.Cube);
g.transform.localScale = new Vector3 (3, 3, 3);
g.transform.renderer.material.mainTexture = t;
g.transform.position = Camera.main.transform.position + (Camera.main.transform.forward * 10);
}
// Update is called once per frame
void Update () {
if (Input.GetMouseButton (0)) {
RaycastHit hit;
if(g.collider.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit,1000))
{
x = g.transform.position.x-hit.point.x;
x = x/g.transform.localScale.x;
x+=.5f;
y = g.transform.position.y-hit.point.y;
y = y/g.transform.localScale.y;
y+=.5f;
t.SetPixel(Mathf.RoundToInt(x*t.width),Mathf.RoundToInt(y*t.height),Color.green);
t.Apply();
}}}
}
This seems to work well enough for me with a plane and a camera in the variables:
Vector3 mousePosition = Input.mousePosition;
Ray screenPosition = _cam.ScreenPointToRay (mousePosition);
if (!_plane.GetComponent<Collider> ().Raycast (screenPosition, out RaycastHit hit, 1000))
{
return;
}
Vector3 hitPoint = _cam.WorldToScreenPoint (hit.point);
Vector3 planeMin = _cam.WorldToScreenPoint (_plane.GetComponent<MeshRenderer> ().bounds.min);
Vector3 planeMax = _cam.WorldToScreenPoint (_plane.GetComponent<MeshRenderer> ().bounds.max);
float xProportion = Mathf.InverseLerp (planeMin.x, planeMax.x, hitPoint.x);
float yProportion = Mathf.InverseLerp (planeMin.y, planeMax.y, hitPoint.y);
float xPoint = xProportion * sourceImage.width;
float yPoint = yProportion * sourceImage.height;
Vector2 startPosition = new Vector2 (xPoint, yPoint);