Unityのメッシュ変形
こんにちは。情報を残せば面白いゲームを誰かが作ってくれると思っている
ゲームプログラマーikosamiです。
この記事は、「Unityでの簡単なメッシュ変形のやり方」の続きです。
前回の記事をまだ見ていない方は、こちらからどうぞ。
マウスカーソルの位置を変形させる
今回の記事では、これの作り方を解説します。
真ん中のPlaneが最初の動画と同じ動きをしていますね。
先に出しますが、ソースコードはこんな感じです。
using UnityEngine;
public class MeshEdit : MonoBehaviour
{
MeshFilter meshFilter;
MeshCollider meshCollider;
//変形する範囲 マウス位置から、どこまでの距離が変形するか
float editDistance = 2f;
private void Start()
{
meshFilter = GetComponent<MeshFilter>();
meshCollider = GetComponent<MeshCollider>();
}
private void Update()
{
//カメラからレイを飛ばす
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Edit(hit.point);
}
}
private void Edit(Vector3 editPoint)
{
Vector3[] vertices = meshFilter.mesh.vertices;
for (int i = 0; i < vertices.Length; i++)
{
var worldPosition = vertices[i] + transform.position;
var distance = Vector3.Distance(worldPosition, editPoint);
if (distance < editDistance)
{
vertices[i] += new Vector3(0, 0.1f * (editDistance - distance), 0);
}
}
meshFilter.mesh.vertices = vertices;
//MeshColliderにメッシュ情報を入れる
meshCollider.sharedMesh = meshFilter.mesh;
}
}
ソースコード以外に必要なもの
見ればわかる人にはわかるとは思いますが、MeshColliderが必須です。
メッシュのあるオブジェクトに、MeshColliderを付け、このMeshEditをつけてください。
前記事で説明した通り、頂点数が少ないものではまともに変形できませんが、
gif動画にある通り、一応なんでも動かすことは可能です。
内容の解説
メッシュ変形しようとしている人なら、わかる人の方が多そうですので、
GetComponentや、カメラからのRayの飛ばし方、Rayとは何かは、
そこから説明すると長くなりすぎるため省略させていただきます。
よくわからない方は、別途検索してみてください。
メッシュ変形自体は、edit関数の中のみなので、そこだけ説明します。
var worldPosition = vertices[i] + transform.position;
前回の記事で説明した通り、メッシュの頂点座標vertices[i]は、オブジェクトの中心位置からの距離になります。
そのままでは、(0,0,0)の位置にあるオブジェクトしか、座標での計算が使えません。
ですので、このようにオブジェクトの座標を加算することによって、Unity空間上の位置を算出できます。
var distance = Vector3.Distance(worldPosition, editPoint);
メッシュ変形特有のものではないので説明が必要かどうかわかりませんが、
2つの座標の距離を算出します。
if (distance < editDistance) {
vertices[i] += new Vector3(0, 0.1f * (editDistance - distance), 0);
}
マウスカーソルの位置とメッシュ頂点の距離が一定以下の場合に、頂点を上昇させる処理です。
距離が近い場所ほど大きく上昇させれば、山のような形になるので、
指定距離 - 距離にすれば、山なりになります。
//MeshColliderにメッシュ情報を入れる
meshCollider.sharedMesh = meshFilter.mesh;
MeshColliderを入れずに、普通のBoxColliderなどで行おうとすると、
メッシュが変形した後の当たり判定が取れないため、上昇した地面にRayが当たりません。
そのため、MeshColliderを入れるわけなのですが、変形後にこのメッシュも更新する必要があります。
それがこの処理です。
終わりに
なんだか、前回の記事に比べて、説明が雑に見えるような気がしますが、
とりあえず、これでメッシュが変形できると思います。
もし不明点があった場合はコメントにお願いします。