(This would be more appropriate as a comment, as I can’t fully provide an answer, but it exceeds the 3000 character limit)
Based on your description, it sounds like the UVs appear correctly in the editor, which means that all the UVs are properly aligned between any given 0-1 UV space range. Specifically, this leads me to believe that the UVs are not crossing any given boundary.
Based on that, perhaps this may be of use to verify whether this is the case:
// ViewUVs.cs
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class ViewUVs : MonoBehaviour
{
[SerializeField, HideInInspector]
Mesh m;
[SerializeField, HideInInspector]
int[] t;
[SerializeField, HideInInspector]
Vector2[] uv;
public bool showGrid = true;
public int gridCount = 5;
public bool subGrid = true;
public float subGridSize = 0.1f;
public Vector3 position = new Vector3(0, 0, 0);
public float scale = 5.0f;
public float rotationAngle = 0;
public Vector3 rotationAxis = Vector3.up;
public Camera cCamera;
void Start()
{
if(gameObject.GetComponent<MeshFilter>() == null)
{
Debug.LogError("MeshFilter not found! Script not added to object.");
DestroyImmediate(this);
}
else
{
m = gameObject.GetComponent<MeshFilter>().sharedMesh;
t = m.triangles;
uv = m.uv;
if(cCamera != null)
{
position = cCamera.transform.position + (cCamera.transform.forward * 3 * scale) + (-cCamera.transform.right * 0.5f * scale) + (-cCamera.transform.up * 0.5f * scale);
cCamera.transform.rotation.ToAngleAxis(out rotationAngle, out rotationAxis);
}
else
{
position = transform.position + (Vector3.up * 5);
}
}
}
void OnDrawGizmos()
{
Quaternion rotation = Quaternion.AngleAxis(rotationAngle, rotationAxis.normalized);
if(showGrid && gridCount > 0)
{
if(subGrid && subGridSize > 0)
{
for(float i = -gridCount + 1; i < gridCount; i += subGridSize)
{
if(!Mathf.Approximately(i, Mathf.RoundToInt(i)))
{
if(i > 0 && i < 1)
{
Gizmos.color = new Color(0.0f, 0.0f, 0.33f);
}
else
{
Gizmos.color = new Color(0.33f, 0.33f, 0.33f);
}
Gizmos.DrawLine(position + (rotation * new Vector3((i * scale), ((-gridCount + 1) * scale), 0)), position + (rotation * new Vector3((i * scale), (gridCount * scale), 0)));
Gizmos.DrawLine(position + (rotation * new Vector3(((-gridCount + 1) * scale), (i * scale), 0)), position + (rotation * new Vector3((gridCount * scale), (i * scale), 0)));
}
}
}
for(int i = (-gridCount + 1) + 1; i < gridCount; i++)
{
if(i == 0 || i == 1)
{
Gizmos.color = new Color(0.66f, 0.0f, 0.0f);
}
else
{
Gizmos.color = new Color(0.66f, 0.66f, 0.66f);
}
Gizmos.DrawLine(position + (rotation * new Vector3((i * scale), ((-gridCount + 1) * scale), 0)), position + (rotation * new Vector3((i * scale), (gridCount * scale), 0)));
Gizmos.DrawLine(position + (rotation * new Vector3(((-gridCount + 1) * scale), (i * scale), 0)), position + (rotation * new Vector3((gridCount * scale), (i * scale), 0)));
}
}
if(t != null && uv != null)
{
Gizmos.color = Color.white;
for(int i = 0; i < t.Length; i += 3)
{
Gizmos.DrawLine(position + (rotation * new Vector3(uv[t<em>].x, uv[t_].y, 0)) * scale, position + (rotation * new Vector3(uv[t[i + 1]].x, uv[t[i + 1]].y, 0)) * scale);_</em>
_ Gizmos.DrawLine(position + (rotation * new Vector3(uv[t[i + 1]].x, uv[t[i + 1]].y, 0)) * scale, position + (rotation * new Vector3(uv[t[i + 2]].x, uv[t[i + 2]].y, 0)) * scale);
Gizmos.DrawLine(position + (rotation * new Vector3(uv[t[i + 2]].x, uv[t[i + 2]].y, 0)) * scale, position + (rotation * new Vector3(uv[t].x, uv[t].y, 0)) * scale);
* }
}
}
}
Specifically, this script will generate a grid (if desired, color-coded to indicate the 0-1 range for the UVs) and a display of the UVs on the object. To start, this would at least help to verify that the coordinates all appear to be in the correct positions.
I can’t say for certain whether it would be easy or reasonable to save the result back out afterward, but the uv positions would be able to be normalized using
for(int i = 0; i < uv.length; i++)
{
uv = new Vector2(Mathf.Repeat(uv.x, 1.0f), Mathf.Repeat(uv.y, 1.0f));
}
… although, that will also only be reasonable if no uv islands cross a whole-number boundary in any given x to (x+1) range.
Edit: Script rewritten. I wasn’t happy with it.*_