Skip to content

Instantly share code, notes, and snippets.

@daichi-takezawa
Created April 28, 2020 17:36
Show Gist options
  • Save daichi-takezawa/25483b68f2174e03d3840a5769a85295 to your computer and use it in GitHub Desktop.
Save daichi-takezawa/25483b68f2174e03d3840a5769a85295 to your computer and use it in GitHub Desktop.
クリックでなぞった場所にMeshが作成されるスクリプト
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter), typeof(MeshCollider))]
public class CreateMeshByMouse : MonoBehaviour
{
private List<Vector2> centerPoints;
[SerializeField] float appendDistance = 0.5f;
//構造体 自分で型と要素数を決められる、要素ごとの型が違う配列。つまり違種類の物をまとめていれれる大きな箱
private struct section
{
public Vector2 direction; // 方向ベクトル.
public Vector2 left; // セクションの左端.
public Vector2 right; // セクションの右側.
}
private section[] necessaryInfo;
[SerializeField] float width = 1;
void Update()
{
setPoints();
setVectors();
createMesh();
}
/// マウス入力によってcenterPointsを設定する.
void setPoints()
{
// マウス押下中のみ処理を行う.
if (!Input.GetMouseButton(0)) return;
// マウスの位置をスクリーン座標からワールド座標に変換.
var screenMousePos = Input.mousePosition;
screenMousePos.z = -Camera.main.transform.position.z;
Vector2 curPoint = Camera.main.ScreenToWorldPoint(screenMousePos);
if (centerPoints == null)
{
centerPoints = new List<Vector2>();
centerPoints.Add(curPoint);
}
// centerPointの距離を測って、無駄な描画はしないようにする
var distance = (curPoint - centerPoints[centerPoints.Count - 1]);
if (distance.magnitude >= appendDistance)
{
centerPoints.Add(curPoint);
}
}
//前後のポイントかポイント自身を用いて傾く方向ベクトルの計算を行う
// 次に、方向ベクトルに垂直に幅を足して両端を求める。
void setVectors()
{
// 2つ以上セクションを用意できない状態の場合処理を抜ける.
if (centerPoints == null || centerPoints.Count <= 1) return;
necessaryInfo = new section[centerPoints.Count];
for (int i = 0; i < centerPoints.Count; i++)
{
// ----- 方向ベクトルの計算 -----
if (i == 0)
{
// 始点の場合.
necessaryInfo[i].direction = centerPoints[i + 1] - centerPoints[i];
}
else if (i == centerPoints.Count - 1)
{
// 終点の場合.
necessaryInfo[i].direction = centerPoints[i] - centerPoints[i - 1];
}
else
{
// 途中の場合.
necessaryInfo[i].direction = centerPoints[i + 1] - centerPoints[i - 1];
}
//Normalizeはmagnitude を 1 としたベクトルを作成します
//正規化されたときベクトルは同じ方向は維持したままで長さが 1.0 のものが作成されます。
necessaryInfo[i].direction.Normalize();
// ----- 方向ベクトルに直交するベクトルの計算 -----
Vector2 side = Quaternion.AngleAxis(90f, -Vector3.forward) * necessaryInfo[i].direction;
side.Normalize();
necessaryInfo[i].left = centerPoints[i] - side * width / 2f;
necessaryInfo[i].right = centerPoints[i] + side * width / 2f;
}
}
//Gizmo(頂点の点)を表示する
void OnDrawGizmos()
{
if (necessaryInfo == null) return;
Gizmos.color = Color.black;
for (int i = 0; i < necessaryInfo.Length; i++)
{
Gizmos.DrawSphere(centerPoints[i], 0.1f);
}
Gizmos.color = Color.blue;
for (int i = 0; i < necessaryInfo.Length; i++)
{
Gizmos.DrawSphere(necessaryInfo[i].left, 0.1f);
Gizmos.DrawSphere(necessaryInfo[i].right, 0.1f);
}
}
void createMesh()
{
if (centerPoints == null || centerPoints.Count <= 1) return;
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = mf.mesh = new Mesh();
mesh.name = "CurveLaserMesh";
int meshCount = centerPoints.Count - 1; // 四角メッシュ生成数はセクション - 1.
Vector3[] vertices = new Vector3[(meshCount) * 4]; // 四角なので頂点数は1つのメッシュに付き4つ.
int[] triangles = new int[(meshCount) * 2 * 3]; // 1つの四角メッシュには2つ三角メッシュが必要. 三角メッシュには3つの頂点インデックスが必要.
// ----- 頂点座標の割り当て -----
for (int i = 0; i < meshCount; i++)
{
vertices[i * 4 + 0] = necessaryInfo[i].left;
vertices[i * 4 + 1] = necessaryInfo[i].right;
vertices[i * 4 + 2] = necessaryInfo[i + 1].left;
vertices[i * 4 + 3] = necessaryInfo[i + 1].right;
}
// ----- 頂点インデックスの割り当て -----
int positionIndex = 0;
for (int i = 0; i < meshCount; i++)
{
triangles[positionIndex++] = (i * 4) + 1;
triangles[positionIndex++] = (i * 4) + 0;
triangles[positionIndex++] = (i * 4) + 2;
triangles[positionIndex++] = (i * 4) + 2;
triangles[positionIndex++] = (i * 4) + 3;
triangles[positionIndex++] = (i * 4) + 1;
}
mesh.vertices = vertices;
mesh.triangles = triangles;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment