Рисование на 3D объекте проблема на Android - Unity C#
Всем привет! Столкнулся с такой проблемой: У меня есть 3D модель, на которой можно рисовать мышкой, как в Paint. В редакторе рисовка по 3D модели работает идеально ,то есть кисть с выбранной краской появляется там где и мышь, но когда дело доходит до Android ,то тут всё печально Пытаюсь рисовать пальцем по модельки ан не получается, кисть не спавнится и всё. Думал в начале о том, что может дело в векторе Input.mousePosition, который нельзя отследить на телефоне и решил его заменить на Input.touches[0].position и да после этого скрипт стал отлавнивать позицию в коде процесс рисования идёт, но на модели почему-то не отображается ,то есть кисть с выбранной краской не спавнится и всё В чем может быть проблема? Прикрепляю полученный код ниже:
public enum ModePaint
{
CaseCameraMove,
BrushPaint,
StickerPaint,
TextMeshWriteRead,
}
public CaseCamera caseCamera;
public ColorPicker colorPicker;
public Texture2D ClearTextureCase;
public Button ButtonUndo, ButtonRedo,ButtonClear;
public Image[] RoflPlitks;
public TextMeshPro NameRoflCaseText;
public GameObject[] SettingsInstuments;
public User user;
internal int CurrentCountTextures = 0;
[SerializeField]internal List<Color[]> Textures = new List<Color[]>();
private float BrushSize = 0.1f;
private Texture2D PaintTexture;
private Color BrushColor;
private ModePaint modePaint;
private RaycastHit rayhit;
void OnMouseDown()
{
if (modePaint == ModePaint.StickerPaint)
{
if(Input.touchCount > 0 && (Input.touches[0].phase == TouchPhase.Began))
Draw(Input.touches[0].position);
}
}
void OnMouseDrag()
{
if(modePaint == ModePaint.BrushPaint)
{
if (Input.touchCount > 0 && (Input.touches[0].phase == TouchPhase.Stationary))
Draw(Input.touches[0].position);
}
}
void OnMouseUp()
{
if (modePaint == ModePaint.BrushPaint)
{
Textures.Add(PaintTexture.GetPixels());
CurrentCountTextures = Textures.Count - 1;
}
}
private void Start()
{
user = colorPicker.user;
NameRoflCaseText.text = "";
Clear();
}
internal void SetBrushSize(float cur)
{
BrushSize = cur;
}
internal void SetBrushColor(Color color)
{
BrushColor = color;
}
public void SelectModePaint(int GetHashCode)
{
foreach (Image i in RoflPlitks)
i.color = Color.white;
foreach (GameObject go in SettingsInstuments)
go.SetActive(false);
RoflPlitks[GetHashCode].color = Color.green;
if(GetHashCode > 0)
SettingsInstuments[GetHashCode - 1].SetActive(true);
caseCamera.enabled = GetHashCode == 0;
modePaint = (ModePaint)GetHashCode;
}
internal ModePaint GetModePaint()
{
return modePaint;
}
void FixedUpdate()
{
CheckUndoRedoClear();
}
public void ChangedTextNameRoflCase(InputField NameRoflCaseInputField)
{
NameRoflCaseText.text = NameRoflCaseInputField.text;
}
#region Undo / Redo
private void CheckUndoRedoClear()
{
ButtonUndo.gameObject.SetActive(modePaint == ModePaint.BrushPaint || modePaint == ModePaint.StickerPaint);
ButtonRedo.gameObject.SetActive(modePaint == ModePaint.BrushPaint || modePaint == ModePaint.StickerPaint);
ButtonClear.gameObject.SetActive(modePaint == ModePaint.BrushPaint || modePaint == ModePaint.StickerPaint);
ButtonUndo.interactable = CurrentCountTextures > 0;
ButtonRedo.interactable = CurrentCountTextures+1 < Textures.Count;
ButtonClear.interactable = Textures.Count > 1;
}
public void Undo()
{
PaintTexture.SetPixels(Textures[CurrentCountTextures - 1]);
PaintTexture.Apply();
CurrentCountTextures--;
}
public void Redo()
{
PaintTexture.SetPixels(Textures[CurrentCountTextures + 1]);
PaintTexture.Apply();
CurrentCountTextures++;
}
public void Clear()
{
if (PaintTexture == null)
InizializationPaintTexture();
else
PaintTexture.SetPixels(ClearTextureCase.GetPixels());
PaintTexture.Apply();
Textures = new List<Color[]>();
Textures.Add(ClearTextureCase.GetPixels());
CurrentCountTextures = Textures.Count-1;
}
private void InizializationPaintTexture()
{
var tex = GetComponent<MeshRenderer>().sharedMaterial.mainTexture as Texture2D;
PaintTexture = new Texture2D(tex.width, tex.height,TextureFormat.RGBA32,false);
PaintTexture.filterMode = FilterMode.Bilinear;
PaintTexture.SetPixels32(tex.GetPixels32());
PaintTexture.Apply();
GetComponent<MeshRenderer>().material.mainTexture = PaintTexture;
}
#endregion
private void Draw(Vector3 pos)
{
Ray hit = caseCamera.GetComponent<Camera>().ScreenPointToRay(pos);
if (Physics.Raycast(hit, out rayhit))
{
MeshRenderer rend = rayhit.transform.GetComponent<MeshRenderer>();
MeshCollider meshCollider = rayhit.collider as MeshCollider;
if (rend == null || rend.sharedMaterial == null || rend.sharedMaterial.mainTexture == null || meshCollider == null)
return;
Vector2 pixelUV = rayhit.textureCoord;
pixelUV.x *= rend.material.mainTexture.width;
pixelUV.y *= rend.material.mainTexture.height;
int x = (int)pixelUV.x;
int y = (int)pixelUV.y;
//Expand where to draw on both direction
if (modePaint == ModePaint.BrushPaint)
{
int radius = Mathf.RoundToInt(BrushSize * 100);
float rSquared = radius * radius;
//Expand where to draw on both direction
for (int u = x - radius; u < x + radius + 1; u++)
for (int v = y - radius; v < y + radius + 1; v++)
if ((x - u) * (x - u) + (y - v) * (y - v) < rSquared)
PaintTexture.SetPixel(u, v, BrushColor);
PaintTexture.Apply();
if (CurrentCountTextures != Textures.Count - 1)
{
for (int i = Textures.Count-1; i > CurrentCountTextures; i--)
{
Textures.RemoveAt(i);
}
CurrentCountTextures = Textures.Count;
}
}
else if (modePaint == ModePaint.StickerPaint && user.StickersBuyes[colorPicker.CurrentStickerSelected])
{
Texture2D sticker = rotate(CreateSticker());
// Map Ray(X, Y) - это процентное положение (варьируемое от 0 до 1) от выходного значения RayCast
// Умножив матрицу на ширину основной текстуры, мы получим плавающую версию матрицы.
// Спрайт CenterX координата, которую он должен быть преобразован в Int, и то же самое для координаты Y.
int MainWidth = PaintTexture.width;// Мы определяем нашу ширину MainTexture
int MainHeight = PaintTexture.height;// Мы определяем нашу основную высоту текстуры
int SpriteCenterX = Mathf.FloorToInt(rayhit.textureCoord.x * MainWidth); // Мы определяем X SpriteCenter
int SpriteCenterY = Mathf.FloorToInt(rayhit.textureCoord.y * MainHeight);// Мы определяем центр Спрайта Y
int FirstPointX = SpriteCenterX - sticker.width / 2; // Определим первую точку (x,y) из...
int FirstPointY = SpriteCenterY - sticker.height / 2;// ...наш спрайт, это точка в левом нижнем углу
Color[] MainColor = PaintTexture.GetPixels(); // Мы собираем основные пиксели цвета текстуры в цветовом массиве
Color[] ResultColor = PaintTexture.GetPixels();// Мы собираем основные пиксели цвета текстуры в цветовом массиве...
Color[] SpriteColor = sticker.GetPixels();
// ...Вызывается результирующий цвет, который будет использоваться для смешивания цветных пикселей
int j = FirstPointY < 0 ? Mathf.Abs(FirstPointY) : 0;//если они нашей первой точки < 0, то j=положительное значение...
// ......из первого пункта вы
while (j < sticker.height)
{
int i = FirstPointX < 0 ? Mathf.Abs(FirstPointX) : 0;//если X нашей первой точки < 0, то i=положительное значение...
// ...из первой точки X
int PointY = FirstPointY + j;// Мы определяем координату Y нашего цветного пикселя в основной текстуре
if (PointY >= MainHeight)
{
j = sticker.height; // Мы заканчиваем цикл j, когда координата цветного пикселя Y достигает...
i = sticker.width; // ...MainTexture haight value а также мы заканчиваем цикл i
}
else
{
while (i < sticker.width)
{
int PointX = FirstPointX + i;// Мы определяем координату X нашего цветного пикселя в основной текстуре
if (PointX < PaintTexture.width)
{
int MainInd = PointY * PaintTexture.width + PointX;// Мы преобразуем координаты X и Y из ...
//......цветной пиксель, расположенный на основной текстуре в массиве to Index
int SpriteInd = j * sticker.width + i;//Мы преобразуем координаты локали X и Y...
float ColorMixA = SpriteColor[SpriteInd].a;
if(ColorMixA == 0)
ResultColor[MainInd] = MainColor[MainInd];
else
ResultColor[MainInd] = SpriteColor[SpriteInd];
}
else { i = PaintTexture.width; }// Мы заканчиваем цикл i, если точка X>=основная текстура.ширина
i++;
}
}
j++;
}
PaintTexture.SetPixels(0,0,PaintTexture.width,PaintTexture.height,ResultColor);
PaintTexture.Apply();
if (CurrentCountTextures != Textures.Count - 1)
{
for (int i = Textures.Count - 1; i > CurrentCountTextures; i--)
{
Textures.RemoveAt(i);
}
CurrentCountTextures = Textures.Count;
}
Textures.Add(PaintTexture.GetPixels());
CurrentCountTextures = Textures.Count-1;
}
}
}
public Texture2D rotate(Texture2D original)
{
Texture2D flipped = new Texture2D(original.width, original.height,TextureFormat.RGBA32,false);
for (int i = 0; i < flipped.width; i++)
{
for (int j = 0; j < flipped.height; j++)
{
flipped.SetPixel(flipped.height - i - 1, j, original.GetPixel(j, i));
}
}
flipped.Apply();
return flipped;
}
Texture2D CreateSticker()
{
return colorPicker.StickerPreview.sprite.texture as Texture2D;
}
}
} Отвечу сразу на вопрос, если он возникнет, почему я пеку в Texture2D по пиксельно, а не использую декали. Так так данную текстуру мне нужно будет отправить на сервер, чтобы игрок перешедший во вкладку сообщество мог увидеть данную 3d модель с текстурой(которая подружается в процессе, если игрок выбрал эту модель из списка) Примечания:
- Скрипт весит на 3D модели на которой я рисую
- PaintCase текстура имеет галочку на Read-Write Enabled
- На компьютере если указать Input.mousePosition в метод Draw всё работает!
- Если тестировать данный код через Unity Remote ,то тоже почему-то всё работает, а вот на самом билде на андроид нет В чем может быть проблема? *Методы OnMouseDown OnMouseUp OnMouseDrag отлично срабатывают на Android при отладке. *Тестировалось на Android - смартфоне LG K7.
- Билд использует API Graphics - OpenGLES2(может дело в нём?)
Ниже прикрепляю скриншоты, что в редакторе рисует,а на Android нет
Как мы видим в Unity Editor кнопка назад актива и при этом на кейсе есть краска
Как мы видим на Android кнопка назад активна а ничего не нарисовалось