#初めに
例えば、キャラクタの表情をテクスチャで貼って、UV座標を変更することで表情を変える、というようなケースがあるかと思います。最近、このようなものに取り組んでいたのですが、自分が引っ掛かった点をご紹介いたします。
1.ボーンの入ったキャラクタはSkinnedMeshRendererのsharedMeshを使う。
2.インスタンス化したsharedMeshを使う。
という2点です。
#MeshRendererがアタッチされているオブジェクトの場合
例えば、CubeのようなプリミティブをUnityのエディタ上で作成すると、このようにMesh FilterとMeshRendererが自動的にアタッチされています。
この場合は、MeshFilterコンポーネントからmeshを取得することができます。meshクラスのメンバにUVがVector2の配列として定義されているので、それを操作すればよいです。
一部抜粋
private Mesh myM;
void Start () {
myMesh = gameObject.GetComponent<MeshFilter>().mesh;
}
void Update(){
Vector2[] nUV = myMesh.uv;
for (int i=0; i < myMesh.uv.Length; i++)
{
nUV[i].x *= 0.99f;
nUV[i].y *= 0.99f;
}
myMesh.uv = nUV;
}
#SkinnedMeshRendererがアタッチされているオブジェクトの場合
多くの場合、キャラクターとして使用したいオブジェクトはボーンで動かすものです。例えば、キャラクターのFBXファイルをインポートして、そのメッシュオブジェクトを見ると、先ほどのMeshFilterやMeshRendererは見当たりません。
よって、先ほどのように、MeshFilterのMeshからUVを操作することはできません。
そのかわり、ボーンで変形されるキャラクタでは、このSkinnedMeshRendererが用いられます。SkinnedMeshRendererからSharedMeshを取得することができ、このSharedMeshのメンバにUVがあるので、それを操作します。
private Mesh myM;
private Mesh Imesh;
// Use this for initialization
void Start()
{
myMesh = gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh;
}
// Update is called once per frame
void Update()
{
Vector2[] nUV = myMesh.uv;
for (int i = 0; i < myMesh.uv.Length; i++)
{
nUV[i].x *= 0.99f;
nUV[i].y *= 0.99f;
}
myMesh.uv = nUV;
}
ところが今回は、このようにUVを操作すると問題が起きます。
UVを操作できるのですが、スクリプトを実行して一度UVを変更してしまうと、実行を停止しても元には戻りません。先ほどのCubeの場合は停止して再実行するとスクリプトによるUVの変更がリセットされているのですが、SkinnedMeshRendererの場合はそうはいかないようです。
#インスタンス化したものを使用することで、元のデータを操作せずに保存しておく
そこで、先ほどのスクリプトに少し手を加えます。
private Mesh myM;
private Mesh Imesh;
// Use this for initialization
void Start()
{
myMesh = gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh;
Imesh = Instantiate(myMesh);
gameObject.GetComponent<SkinnedMeshRenderer>().sharedMesh = Imesh;
}
// Update is called once per frame
void Update()
{
Vector2[] nUV = Imesh.uv;
for (int i = 0; i < Imesh.uv.Length; i++)
{
nUV[i].x *= 0.99f;
nUV[i].y *= 0.99f;
}
Imesh.uv = nUV;
}
sharedMeshをInstantiate()でインスタンス化して、sharedMeshの参照先をインスタンスに変更します。
こうしてから、インスタンスを操作すれば先ほどのような問題は起こらず、実行を停止すれば、UVへの変更はリセットされます。
余談ですが、これで、UVだけでなく頂点も弄り放題です。
また、UVを変更する場合に限らず、色々な場合に応用できると思われます。