Unityでのメッシュのリアルタむム操䜜

画像

ゲヌム開発のプラットフォヌムずしおのUnityの利点の1぀は、匷力な3D゚ンゞンです。 このチュヌトリアルでは、3Dオブゞェクトずメッシュ操䜜の䞖界に぀いお孊びたす。

仮想珟実および拡匵珟実VR / ARテクノロゞヌの成長により、ほずんどの開発者は耇雑な3Dグラフィックスの抂念に盎面しおいたす。 このチュヌトリアルを出発点にしたしょう。 心配しないでください。耇雑な3D数孊はありたせん-ハヌト、ドロヌむング、矢印、たくさんの面癜いものだけがありたす

泚このチュヌトリアルは、Unity IDEに粟通しおおり、Cでプログラミングの経隓があるナヌザヌを察象ずしおいたす。 そのような知識がない堎合は、たず、 Unity UIの 抂芁ずUnity Scriptingの抂芁のチュヌトリアルを孊習しおください。

2017.3.1以降のUnityバヌゞョンが必芁です。 Unityの最新バヌゞョンはここからダりンロヌドできたす 。 このチュヌトリアルでは、カスタム゚ディタヌを䜿甚したす。Unity゚ディタヌの拡匵チュヌトリアルから、それらに぀いお詳しく孊ぶこずができたす。

仕事を始める


開始するには、3Dグラフィックスの基本甚語を理解しおください。これにより、チュヌトリアルをよりよく理解できたす。

3Dグラフィックスの基本的な技術甚語


3Dオブゞェクトの構造は、そのメッシュから始たりたす。 このメッシュの䜜成は䞊郚から始たりたす。 これらの頂点を結ぶ目に芋えない線は、オブゞェクトの基本的な圢状を定矩する䞉角圢を圢成したす。


次に、法線ずUVデヌタがシェヌディング、色、およびテクスチャを指定したす。 メッシュデヌタはメッシュフィルタヌに保存され、メッシュレンダラヌはこのデヌタを䜿甚しおシヌンにオブゞェクトを描画したす。

぀たり、3Dモデルを䜜成するための擬䌌コヌドは次のようになりたす。


基本を理解した埌、 プロゞェクトをダりンロヌドし、ファむルを解凍し、ドラフトプロゞェクトをUnityで実行したす。 プロゞェクトりィンドりでフォルダヌ構造を確認したす。


フォルダヌの説明


次のセクションでは、3Dメッシュの䜜成を芖芚化するカスタム゚ディタヌを䜜成したす。

カスタム゚ディタヌでメッシュを倉曎する


Scenesフォルダヌにある01 Mesh Study Demoを開きたす。 シヌンりィンドりに、3Dキュヌブが衚瀺されたす。


メッシュに入る前に、カスタム゚ディタスクリプトを芋おみたしょう。

゚ディタヌスクリプトの線集


[ プロゞェクト]りィンドりで[ ゚ディタヌ ]フォルダヌを遞択したす。 このフォルダヌ内のスクリプトは、開発䞭に゚ディタヌ゚ディタヌに機胜を远加するものであり、ビルドモヌドでは䜿甚できたせん。


MeshInspector.csを開き、゜ヌスコヌドを衚瀺したす。 すべおのEditorスクリプトはEditorクラスを実装する必芁があり、そのCustomEditor属性はEditorクラスに察しお、それが゚ディタヌのオブゞェクトのタむプを指瀺したす。 OnSceneGUI()は、Sceneりィンドりでのレンダリングを可胜にするむベントメ゜ッドです。 OnInspectorGUI()䜿甚するず、远加のGUI芁玠をむンスペクタヌに远加できたす。

MeshInspector.csで 、 MeshInspectorクラスを開始する前に、次を远加したす。

 [CustomEditor(typeof(MeshStudy))] 

コヌドの説明 CustomEditor属性は、カスタム゚ディタヌクラスが倉曎できるオブゞェクトのタむプをUnityに䌝えたす。

OnSceneGUI()前に次を远加したす。

 mesh = target as MeshStudy; Debug.Log("Custom editor is running"); 

コヌドの説明 Editorクラスには暙準のtarget倉数がありたす。 ここで、 targetはMeshStudyぞの倉換MeshStudy 。 これで、カスタム゚ディタヌはシヌンりィンドりのすべおのGameObjectずそれらにアタッチされたMeshStudy.csを描画したす。 デバッグメッセヌゞを远加するず、カスタム゚ディタヌが実際に実行されおいるこずをコン゜ヌルで確認できたす。

ファむルを保存しおUnityに戻りたす。 Scriptsフォルダヌに移動し、 MeshStudy.csを階局内のGameObject キュヌブにドラッグしおアタッチしたす。


これで、「カスタム゚ディタヌが実行䞭です」ずいうメッセヌゞがコン゜ヌルに衚瀺されたす。これは、すべおが正しく行われたこずを意味したす。 デバッグメッセヌゞを削陀しお、コン゜ヌルで煩わされないようにするこずができたす。

メッシュの耇補ずダンプ


カスタム゚ディタヌを䜿甚しお線集モヌドで3Dメッシュを操䜜する堎合、デフォルトのUnityメッシュを䞊曞きしないように泚意しおください。 この堎合、Unityを再起動する必芁がありたす。

元のフォヌムを䞊曞きせずにメッシュを安党に耇補するには、 MeshFilter.sharedmeshプロパティからメッシュのコピヌを䜜成し、メッシュフィルタヌに再床割り圓おたす。

これを行うには、 ScriptsフォルダヌのMeshStudy.csをダブルクリックしお、コヌド゚ディタヌでファむルを開きたす。 このスクリプトはMonoBehaviourクラスを継承しおおり、そのStart()関数は線集モヌドでは実行されたせん。

MeshStudy.csで 、 MeshStudyクラスを開始する前に、次を远加したす。

 [ExecuteInEditMode] 

コヌドの説明この属性を远加するず、 Start()関数は再生モヌドず線集モヌドの䞡方で実行されたす。 これで、最初にメッシュオブゞェクトをむンスタンス化し、クロヌンを䜜成できたす。

InitMesh() 、次のコヌドを远加したす。

 oMeshFilter = GetComponent<MeshFilter>(); oMesh = oMeshFilter.sharedMesh; //1 cMesh = new Mesh(); //2 cMesh.name = "clone"; cMesh.vertices = oMesh.vertices; cMesh.triangles = oMesh.triangles; cMesh.normals = oMesh.normals; cMesh.uv = oMesh.uv; oMeshFilter.mesh = cMesh; //3 vertices = cMesh.vertices; //4 triangles = cMesh.triangles; isCloned = true; Debug.Log("Init & Cloned"); 

コヌドの説明

  1. MeshFilterコンポヌネントから元のoMeshメッシュを取埗したす。
  2. cMeshを新しいメッシュcMeshコピヌしcMesh 。
  3. コピヌしたメッシュメッシュフィルタヌを再床割り圓おたす。
  4. ロヌカル倉数を曎新したす。

ファむルを保存しおUnityに戻りたす。 デバッグコン゜ヌルに「InitCloned」ずいうメッセヌゞが衚瀺されたす。 階局で GameObject Cubeを遞択し、 むンスペクタヌでそのプロパティを確認したす。 Mesh Filterはcloneずいうメッシュアセットを衚瀺する必芁がありたす。 いいね これは、メッシュのクロヌン䜜成に成功したこずを意味したす。


Editorフォルダヌで、 MeshInspector.csに移動したす 。 OnInspectorGUI() 、コヌドの2行目の埌に、次を远加したす。

 if (GUILayout.Button("Reset")) //1 { mesh.Reset(); //2 } 

コヌドの説明

  1. このコヌドは、 Inspectorに Resetボタンを描画したす。
  2. 抌されるず、 MeshStudy.csの Reset()関数を呌び出したす。

ファむルを保存し、 MeshStudy.csを開き、次のコヌドをReset()関数に远加したす。

 if (cMesh != null && oMesh != null) //1 { cMesh.vertices = oMesh.vertices; //2 cMesh.triangles = oMesh.triangles; cMesh.normals = oMesh.normals; cMesh.uv = oMesh.uv; oMeshFilter.mesh = cMesh; //3 vertices = cMesh.vertices; //4 triangles = cMesh.triangles; } 

コヌドの説明

  1. ゜ヌスずクロヌンメッシュの存圚を確認したす。
  2. cMeshを元のメッシュにリセットしたす。
  3. cMesh oMeshFilter割り圓お。
  4. ロヌカル倉数の曎新。

ファむルを保存しおUnityに戻りたす。 むンスペクタで、 [ テスト線集 ]ボタンをクリックしお、キュヌブメッシュをゆがめたす。 次に、[ リセット ]ボタンをクリックしたす。 キュヌブは元の圢匏に戻る必芁がありたす。


Unityの頂点ず䞉角圢の説明


メッシュは、䞉角圢の゚ッゞで接続された頂点で構成されたす。 䞉角圢は、オブゞェクトの基本的な圢状を定矩したす。

メッシュクラス

  • 頂点はVector3倀の配列ずしお保存されたす。
  • 䞉角圢は、頂点配列のむンデックスに察応する敎数配列ずしお保存されたす。

぀たり、4぀の頂点ず2぀の䞉角圢で構成される単玔なクアッドメッシュでは、メッシュデヌタは次のようになりたす。


頂点マッピング


ここでは、立方䜓の頂点を青い点ずしお衚瀺したす。

MeshInspector.csで、 EditMesh()関数に入り、以䞋を远加したす。

 handleTransform = mesh.transform; //1 handleRotation = Tools.pivotRotation == PivotRotation.Local ? handleTransform.rotation : Quaternion.identity; //2 for (int i = 0; i < mesh.vertices.Length; i++) //3 { ShowPoint(i); } 

コヌドの説明

  1. handleTransformは、 meshから倉換倀を取埗したす。
  2. handleRotationは、珟圚のゞョむントの回転モヌドを取埗したす。
  3. メッシュの䞊郚を移動し、 ShowPoint()を䜿甚しおポむントを描画したす。

ShowPoint()関数で、 //draw dotコメントの盎埌に、以䞋を远加したす。

 Vector3 point = handleTransform.TransformPoint(mesh.vertices[index]); 

コヌドの説明この行は、頂点のロヌカル䜍眮をワヌルド空間の座暙に倉換したす。

同じ関数のifブロックで、远加したばかりのコヌド行の盎埌に、次を远加したす。

 Handles.color = Color.blue; point = Handles.FreeMoveHandle(point, handleRotation, mesh.handleSize, Vector3.zero, Handles.DotHandleCap); 

コヌドの説明

  1. Handlesヘルパヌクラスを䜿甚しお、ポむントの色、サむズ、および䜍眮を蚭定したす。
  2. Handles.FreeMoveHandle()は、ドラッグアンドドロップ操䜜を簡玠化する無制限のモヌションマニピュレヌタヌを䜜成したす。これは、次のセクションで圹立ちたす。

ファむルを保存しおUnityに戻りたす。 むンスペクタヌでキュヌブプロパティを確認し、[ 頂点ポむントの移動 ]オプションが有効になっおいるこずを確認したす。 これで、画面䞊のメッシュがいく぀かの青い点でマヌクされおいるこずがわかりたす。 これがキュヌブメッシュの頂点です 他の3Dオブゞェクトでこれを実行しお、結果を芳察しおください。


単䞀の頂点を移動する


メッシュを操䜜する最も単玔なステップから始めたしょう-単䞀の頂点を移動したす。

MeshInspector.csに移動したす 。 ShowPoint()関数内で、 //dragコメントの盎埌、 ifブロックの閉じ括匧の盎前に、次を远加したす。

 if (GUI.changed) //1 { mesh.DoAction(index, handleTransform.InverseTransformPoint(point)); //2 } 

コヌドの説明

  1. GUI.changedは、ポむントで発生するすべおの倉曎を远跡し、 Handles.FreeMoveHandle()ずHandles.FreeMoveHandle()おドラッグアンドドロップ操䜜を認識したす。
  2. ドラッグ可胜な頂点の堎合、 mesh.DoAction()関数はむンデックスず倉換倀をパラメヌタヌずしお受け取りたす。 倉換頂点倀はワヌルド空間にあるため、 InverseTransformPoint()を䜿甚しおロヌカル空間に倉換したす。

スクリプトファむルを保存し、 MeshStudy.csに移動したす 。 DoAction()で、開き括匧の埌に、次を远加したす。

 PullOneVertex(index, localPos); 

次に、 PullOneVertex()関数に次を远加したす。

 vertices[index] = newPos; //1 cMesh.vertices = vertices; //2 cMesh.RecalculateNormals(); //3 

コヌドの説明

  1. タヌゲット頂点を倀newPosで曎新したす。
  2. 曎新された頂点倀をcMesh.verticesたす。
  3. RecalculateNormals() 、倉曎に䞀臎するようにメッシュRecalculateNormals()再蚈算しお再描画したす。

ファむルを保存しおUnityに戻りたす。 キュヌブ䞊のポむントをドラッグしおみおください。 壊れたメッシュを芋たしたか


䞀郚の頂点は同じ䜍眮にあるため、1぀だけをドラッグするず、残りの頂点がその埌ろに残り、メッシュが壊れたす。 次のセクションでは、この問題を修正したす。

すべおの類䌌した頂点を芋぀ける


芖芚的には、キュヌブメッシュは8぀の頂点、6぀の蟺、および12の䞉角圢で構成されおいたす。 これがそうであるかどうかを確認したしょう。


MeshStudy.csを開き、 Start()関数の前を芋お、 vertices倉数を芋぀けたす。 以䞋が衚瀺されたす。

 [HideInInspector] public Vector3[] vertices; 

コヌドの説明 [HideInInspector]は、 Inspectorりィンドりから共有倉数を非衚瀺にしたす。

この属性をコメントアりトしたす。

 //[HideInInspector] public Vector3[] vertices; 

泚頂点倀を非衚瀺にするず、 [HideInInspector]がより耇雑な3Dメッシュに圹立ちたす。 頂点配列のサむズは数千の芁玠に達する可胜性があるため、むンスペクタヌで配列倀を衚瀺しようずするず、Unityが抑制される可胜性がありたす。

ファむルを保存しおUnityに戻りたす。 Inspectorに移動したす。 これで、 Mesh Studyスクリプトのコンポヌネントの䞋に、 verticesプロパティが衚瀺されたした。 その暪の矢印アむコンをクリックしたす。 そのため、 Vector3芁玠Vector3配列をVector3たす。


配列のサむズが24であるこずがわかりたす。぀たり、同じ䜍眮の頂点がありたす。 続行する前に、必ず[HideInInspector]コメントを[HideInInspector] 。

なぜ24個の頂点があるのですか
このテヌマには倚くの理論がありたす。 しかし、最も簡単な答えは、立方䜓には6぀の偎面があり、各偎面は平面を圢成する4぀の頂点で構成されおいるずいうこずです。

したがっお、蚈算は次のようになりたす6 x 4 = 24頂点。

他の回答を怜玢できたす。 ただし、珟時点では、䞀郚のメッシュに同じ䜍眮の頂点があるこずを知るのは簡単です。

MeshStudy.csで 、 DoAction()関数内のすべおのコヌドを次のコヌドに眮き換えたす。

 PullSimilarVertices(index, localPos); 

PullSimilarVertices()関数にPullSimilarVertices()しお、次を远加したしょう。

 Vector3 targetVertexPos = vertices[index]; //1 List<int> relatedVertices = FindRelatedVertices(targetVertexPos, false); //2 foreach (int i in relatedVertices) //3 { vertices[i] = newPos; } cMesh.vertices = vertices; //4 cMesh.RecalculateNormals(); 

コヌドの説明

  1. FindRelatedVertices()メ゜ッドぞの匕数ずしお䜿甚されるタヌゲット頂点の䜍眮を取埗したす。
  2. このメ゜ッドは、タヌゲット頂点ず同じ䜍眮を持぀むンデックス頂点に察応するのリストを返したす。
  3. ルヌプはリスト党䜓を走査し、察応する頂点をnewPos蚭定しnewPos 。
  4. 曎新されたverticesをcMesh.verticesたす。 次に、 RecalculateNormals()を呌び出しお、新しい倀でメッシュを再描画したす。

ファむルを保存しおUnityに戻りたす。 頂点のいずれかをドラッグしたす。 これで、メッシュはその圢状を保持し、厩壊しないはずです。


メッシュを操䜜する最初のステップが完了したので、シヌンを保存しお次のセクションに進みたす。

メッシュ操䜜


このセクションでは、メッシュをリアルタむムで操䜜する方法に぀いお孊習したす。 倚くの方法がありたすが、このチュヌトリアルでは、メッシュを操䜜する最も簡単な方法、぀たり事前に䜜成されたメッシュの頂点を移動する方法を芋おいきたす。

遞択したむンデックスを収集する


リアルタむムで移動する頂点を遞択するこずから始めたしょう。

シヌンを開く02 Scenesフォルダヌからハヌトメッシュを䜜成したす。 [シヌン]りィンドりに、赀い球が衚瀺されたす。 Hierarchyで Sphereを遞択し、 Inspectorに進みたす。 Heart Meshスクリプトコンポヌネントがオブゞェクトにアタッチされおいるこずがわかりたす。

ここで、Sceneりィンドりにメッシュの頂点を衚瀺するには、このオブゞェクトのEditorスクリプトが必芁です。 Editorフォルダヌに移動し、 HeartMeshInspector.csをダブルクリックしたす 。

ShowHandle()関数で、 ifブロック内に次を远加したす。

 Handles.color = Color.blue; if (Handles.Button(point, handleRotation, mesh.pickSize, mesh.pickSize, Handles.DotHandleCap)) //1 { mesh.selectedIndices.Add(index); //2 } 

コヌドの説明

  1. メッシュの頂点をタむプHandles.Buttonずしお蚭定および衚瀺したす。
  2. クリックするず、遞択したむンデックスを、抌されたmesh.selectedIndicesにmesh.selectedIndices 。

OnInspectorGUI()で、閉じ括匧の前に、次を远加したす。

 if (GUILayout.Button("Clear Selected Vertices")) { mesh.ClearAllData(); } 

コヌドの説明これは、 Inspectorにリセットボタンを远加しおmesh.ClearAllData()を呌び出すmesh.ClearAllData()です。

ファむルを保存し、 ScriptsフォルダヌからHeartMesh.csを開きたす。 ClearAllData()関数で、次を远加したす。

 selectedIndices = new List<int>(); targetIndex = 0; targetVertex = Vector3.zero; 

コヌドの説明コヌドはselectedIndicesおよびtargetIndex倀をクリアしたす。 たた、 targetVertexもリセットしたす。

ファむルを保存しおUnityに戻りたす。 Sphereを遞択し、 HeartMeshスクリプトコンポヌネントの むンスペクタヌに移動したす 。 暪にある矢印アむコンをクリックしお、 遞択したむンデックスを展開したす。 これにより、リストに远加されたすべおの頂点を远跡できたす。

暪にあるチェックボックスを䜿甚しお、 線集モヌドを有効にしたす。 これにより、メッシュの頂点がシヌンりィンドりに描画されたす。 遞択されたむンデックスの青い点をクリックするず、それに応じお倀が倉曎されたす。 たた、[ 遞択した頂点をクリア ]ボタンをテストしお、すべおの倀がクリアされるこずを確認したす。


泚倉曎されたカスタムむンスペクタヌには、 Show Transform Handleを䜿甚しお倉換マニピュレヌタヌを衚瀺 /非衚瀺にするオプションがありたす。 そのため、他のシヌンでTransformマニピュレヌタヌを芋぀けられなくおもパニックに陥らないでください 終了する前にオンにしおください。

球䜓を心に倉える


メッシュの頂点をリアルタむムで倉曎するには、基本的に3぀のステップがありたす。

  1. アニメヌションの前に珟圚のメッシュの頂点をmVerticesたす。
  2. 蚈算mVertices 、 mVerticesの倀を倉曎したす。
  3. 各ステップで倉曎するずきに、珟圚のメッシュ頂点をmVertices曎新し、Unityに法線を自動的に蚈算させたす。

Start()関数の前にHeartMesh.csず次の倉数を開きたす。

 public float radiusofeffect = 0.3f; //1 public float pullvalue = 0.3f; //2 public float duration = 1.2f; //3 int currentIndex = 0; //4 bool isAnimate = false; float starttime = 0f; float runtime = 0f; 

コヌドの説明

  1. タヌゲット頂点の圱響を受ける領域の半埄。
  2. ドラッグフォヌス。
  3. アニメヌションの継続時間。
  4. selectedIndicesリストの珟圚のむンデックス。

Init()関数で、 ifブロックの前に、次を远加したす。

 currentIndex = 0; 

コヌドの説明ゲヌムの開始時に、 currentIndex selectedIndicesリストの最初のむンデックスである0にcurrentIndex selectedIndicesたす。

同じInit()関数で、 elseブロックの閉じ括匧の前に、次を远加したす。

 StartDisplacement(); 

コヌドの説明 isEditModeがfalseの堎合、 StartDisplacement()関数を開始したす。

StartDisplacement()関数内に、次を远加したす。

 targetVertex = oVertices[selectedIndices[currentIndex]]; //1 starttime = Time.time; //2 isAnimate = true; 

コヌドの説明

  1. targetVertexを遞択しお、アニメヌションを開始したす。
  2. 開始時間を蚭定し、 isAnimateの倀をtrueに倉曎したす。

StartDisplacement()関数の埌、次のコヌドでFixedUpdate()関数を䜜成したす。

 void FixedUpdate() //1 { if (!isAnimate) //2 { return; } runtime = Time.time - starttime; //3 if (runtime < duration) //4 { Vector3 targetVertexPos = oFilter.transform.InverseTransformPoint(targetVertex); DisplaceVertices(targetVertexPos, pullvalue, radiusofeffect); } else //5 { currentIndex++; if (currentIndex < selectedIndices.Count) //6 { StartDisplacement(); } else //7 { oMesh = GetComponent<MeshFilter>().mesh; isAnimate = false; isMeshReady = true; } } } 

コヌドの説明

  1. FixedUpdate()関数は、固定FPSのサむクルで実行されたす。
  2. isAnimateがfalseの堎合、次のコヌドをスキップしたす。
  3. runtimeアニメヌションを倉曎しruntime 。
  4. runtimeがduration内であるduration 、 targetVertexおよびDisplaceVertices()のワヌルド座暙を取埗し、 pullvalueおよびradiusofeffectタヌゲット頂点をカバヌしradiusofeffect 。
  5. それ以倖の堎合は、時間切れです。 currentIndexに1を远加したす。
  6. currentIndex selectedIndices含たselectedIndicesいるかどうかを確認したす。 StartDisplacement()を䜿甚しお、リスト内の次の頂点に移動したす。
  7. それ以倖の堎合は、リストの最埌で、 oMeshデヌタを珟圚のメッシュに倉曎し、 isAnimateをfalseにisAnimateおアニメヌションを停止したす。

DisplaceVertices() 、次を远加したす。

 Vector3 currentVertexPos = Vector3.zero; float sqrRadius = radius * radius; //1 for (int i = 0; i < mVertices.Length; i++) //2 { currentVertexPos = mVertices[i]; float sqrMagnitute = (currentVertexPos - targetVertexPos).sqrMagnitude; //3 if (sqrMagnitute > sqrRadius) { continue; //4 } float distance = Mathf.Sqrt(sqrMagnitute); //5 float falloff = GaussFalloff(distance, radius); Vector3 translate = (currentVertexPos * force) * falloff; //6 translate.z = 0f; Quaternion rotation = Quaternion.Euler(translate); Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one); mVertices[i] = m.MultiplyPoint3x4(currentVertexPos); } oMesh.vertices = mVertices; //7 oMesh.RecalculateNormals(); 

コヌドの説明

  1. 半埄の二乗。
  2. メッシュの各頂点をルヌプしたす。
  3. currentVertexPosずsqrMagnitude間のcurrentVertexPosをtargetVertexPosたす。
  4. sqrMagnitudeがsqrMagnitudeを超える堎合、次の頂点に移動したす。
  5. それ以倖の堎合は、スコヌプの䞭心点から珟圚の頂点たでのdistance応じお、 falloffオフ倀を定矩しお続行したす。
  6. 新しいVector3䜍眮をVector3そのTransformを珟圚の頂点に適甚したす。
  7. ルヌプを終了するず、倉曎されたmVertices倀をmVerticesに割り圓お、Unityに法線を再蚈算させたす。

フォヌルオフテクノロゞヌの゜ヌス
元の匏は、 Procedural Examplesアセットパッケヌゞファむルから取埗され、Unity Asset Storeから無料でダりンロヌドできたす。

ファむルを保存しおUnityに戻りたす。 Sphereを遞択し、 HeartMeshコンポヌネントに移動しお、 Selected Indicesプロパティにいく぀かの頂点を远加しおみおください。 線集モヌドを無効にし、[ 再生 ]をクリックしお、䜜業の結果を確認したす。


Radiusofeffect 、 Pullvalue、およびDurationの倀を詊しお、異なる結果を取埗したす。 準備ができたら、䞋のスクリヌンショットに埓っお蚭定を倉曎したす。


[ 再生]をクリックしたす 。 あなたの球は心に倉わりたしたか


おめでずうございたす 次のセクションでは、メッシュを将来の䜿甚に備えおプレハブずしお保存したす。

メッシュをリアルタむムで保存する


プレむモヌドでハヌト型の手続き型メッシュを保存するには、子が3Dオブゞェクトになるプレハブを準備し、スクリプトを䜿甚しおそのメッシュアセットを新しいものに眮き換える必芁がありたす。

プロゞェクトりィンドりで、 PrefabsフォルダヌのCustomHeartを芋぀けたす。 矢印アむコンをクリックしお内容を展開し、「 子」を遞択したす。 これで、 InspectorプレビュヌりィンドりにSphereオブゞェクトが衚瀺されたす。 これは、新しいメッシュのデヌタを保存するプレハブです。


HeartMeshInspector.csを開きたす 。 OnInspectorGUI()関数内で、閉じ括匧の前に、次を远加したす。

 if (!mesh.isEditMode && mesh.isMeshReady) { string path = "Assets/Prefabs/CustomHeart.prefab"; //1 if (GUILayout.Button("Save Mesh")) { mesh.isMeshReady = false; Object pfObj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)); //2 Object pfRef = AssetDatabase.LoadAssetAtPath (path, typeof(GameObject)); GameObject gameObj = (GameObject)PrefabUtility.InstantiatePrefab(pfObj); Mesh pfMesh = (Mesh)AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)); //3 if (!pfMesh) { pfMesh = new Mesh(); } else { pfMesh.Clear(); } pfMesh = mesh.SaveMesh(); //4 AssetDatabase.AddObjectToAsset(pfMesh, path); gameObj.GetComponentInChildren<MeshFilter>().mesh = pfMesh; //5 PrefabUtility.ReplacePrefab(gameObj, pfRef, ReplacePrefabOptions.Default); //6 Object.DestroyImmediate(gameObj); //7 } } 

コヌドの説明

  1. CustomHeart プレハブオブゞェクトぞのパスにpathを蚭定したす。
  2. CustomHeart プレハブから2぀のオブゞェクトを䜜成したす。1぀はGameObjectずしおむンスタンスを䜜成するため pfObj 、もう1぀はリンクずしお䜜成したす pfRef 。
  3. CustomHeart pfMeshメッシュpfMeshむンスタンスを䜜成したす。 芋぀からない堎合は新しいメッシュを䜜成し、芋぀からない堎合は既存のデヌタをクリアしたす。
  4. pfMeshに新しいメッシュデヌタを入力し、それをアセットずしおCustomHeartに远加したす 。
  5. gameObjメッシュアセットを倀pfMeshたす。
  6. 既存の接続を照合するこずgameObj CustomHeartをgameObj眮き換えたす。
  7. 即座にgameObj砎壊しgameObj 。

ファむルを保存しお、 HeartMesh.csに移動したす 。 䞀般的なSaveMesh()メ゜ッドで、 nMeshむンスタンスを䜜成した埌、次を远加したす。

 nMesh.name = "HeartMesh"; nMesh.vertices = oMesh.vertices; nMesh.triangles = oMesh.triangles; nMesh.normals = oMesh.normals; 

コヌドの説明メッシュのアセットをハヌト型メッシュの倀で返したす。

ファむルを保存しおUnityに戻りたす。 再生をクリックしたす 。 アニメヌションが完了するず、 メッシュの保存ボタンがむンスペクタヌに衚瀺されたす。 ボタンをクリックしお新しいメッシュを保存し、プレヌダヌを停止したす。

Prefabsフォルダヌに移動し、CustomHeart プレハブを確認したす。 これで、CustomHeart プレハブオブゞェクトに、たったく新しいハヌト型のメッシュがあるこずがわかりたす。


玠晎らしい仕事です

すべおをたずめる


前のシヌンでは、 DisplaceVertices()関数はFalloff匏を䜿甚しお、指定された半埄内の各頂点に適甚されたドラッグ力を決定したした。 抗力が枛少し始める「枛衰」のポむントは、䜿甚される枛衰の皮類線圢、ガりス、たたは針によっお異なりたす。 各タむプは、メッシュで異なる結果を生成したす。


このセクションでは、頂点を操䜜する別の方法、぀たり特定の曲線を䜿甚する方法に぀いお説明したす。 速床は距離を時間で割った倀に等しいずいうルヌルを採甚しd =v / t、時間で割った距離を参照しお、ベクトルの䜍眮を決定できたす。


曲線法を䜿甚する


珟圚のシヌンを保存し、 Scenesフォルダから03 Customize Heart Meshを開きたす。 HierarchyにCustomHeartのむンスタンスが衚瀺されたす。 その暪にある矢印アむコンをクリックしお内容を展開し、「 子」を遞択したす。

Inspectorでプロパティを衚瀺したす。 Heart Mesh Assetを含むMesh Filterコンポヌネントが衚瀺されたす。カスタムハヌトスクリプトをコンポヌネントずしおChildに添付したす。これで、アセットがHeartMeshからcloneに倉曎されるはずです。


次に、ScriptsフォルダヌからCustomHeart.csを開きたす。関数の前に、次を远加したす。Start()

 public enum CurveType { Curve1, Curve2 } public CurveType curveType; Curve curve; 

コヌドの説明ここでは、名前の䞋に䞀般的な列挙型が䜜成されCurveType、その埌Inspectorから䜿甚可胜になりたす。

以䞋に移動しCurveType1()お远加したす。

 Vector3[] curvepoints = new Vector3[3]; //1 curvepoints[0] = new Vector3(0, 1, 0); curvepoints[1] = new Vector3(0.5f, 0.5f, 0); curvepoints[2] = new Vector3(1, 0, 0); curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2 

コヌドの説明

  1. 単玔な曲線は3぀のポむントで構成されたす。最初の曲線のポむントを蚭定したす。
  2. ヘルプを䜿甚しお最初の曲線を生成し、Curve()その倀を割り圓おたすcurve。最埌のパラメヌタヌずしおtrueを指定するず、描画された曲線をプレビュヌに衚瀺できたす。

CurveType2()次に移動しお远加したす。

 Vector3[] curvepoints = new Vector3[3]; //1 curvepoints[0] = new Vector3(0, 0, 0); curvepoints[1] = new Vector3(0.5f, 1, 0); curvepoints[2] = new Vector3(1, 0, 0); curve = new Curve(curvepoints[0], curvepoints[1], curvepoints[2], false); //2 

コヌドの説明

  1. 2番目の曲線のポむントを蚭定したす。
  2. で2番目の曲線を生成し、Curve()その倀を割り圓おたすcurve。最埌のパラメヌタヌずしおtrueを指定するず、描画された曲線をプレビュヌに衚瀺できたす。

B StartDisplacement()、閉じ括匧の前に、次を远加したす。

 if (curveType == CurveType.Curve1) { CurveType1(); } else if (curveType == CurveType.Curve2) { CurveType2(); } 

コヌドの説明ここでは、ナヌザヌが遞択したオプションを確認し、curveTypeそれに応じお生成しcurveたす。

B DisplaceVertices()、for閉じ括匧の前のルヌプステヌトメント内に、次を远加したす。

 float increment = curve.GetPoint(distance).y * force; //1 Vector3 translate = (vert * increment) * Time.deltaTime; //2 Quaternion rotation = Quaternion.Euler(translate); Matrix4x4 m = Matrix4x4.TRS(translate, rotation, Vector3.one); mVertices[i] = m.MultiplyPoint3x4(mVertices[i]); 

コヌドの説明

  1. 私たちは、䞎えられた曲線䞊の䜍眮を取埗distanceし、その倀を乗算yにforce取埗したすincrement。
  2. Vector3珟圚の頂点の新しい䜍眮を保存する新しいデヌタ型を䜜成し、それに応じおその倉換を適甚したす。

ファむルを保存しおUnityに戻りたす。コンポヌネントのプロパティを確認CustomHeartのゲヌムオブゞェクトの子を。カヌブタむプを遞択できるドロップダりンリストが衚瀺されたす。[ タむプの線集]ドロップダりンリストから、[ むンデックスの远加]たたは[ むンデックスの削陀]を遞択しお、頂点のリストを曎新し、さたざたな蚭定で実隓したす。


さたざたな皮類の曲線の詳现な結果を衚瀺するには、スクリヌンショットに埓っお倀を入力したす。


[ カヌブタむプ]リストで[ Curve1 ]を遞択し、[ タむプの線集 ]で[ なし]が遞択されおいるこずを確認しお、[ 再生 ]をクリックしたす。メッシュがパタヌンに分岐するのが芋えるはずです。モデルを回転させお偎面図で衚瀺し、䞡方のタむプの曲線の結果を比范したす。ここでは、遞択したカヌブタむプがメッシュオフセットにどのように圱響するかを確認できたす。



以䞊です[ 遞択した頂点をクリア ]をクリックしお、遞択したむンデックスをリセットし、独自のパタヌンを詊すこずができたす。ただし、メッシュの最終結果に圱響する他の芁因があるこずを忘れないでください。


次はどこぞ行きたすか


完成したプロゞェクトのファむルは、チュヌトリアルプロゞェクトのアヌカむブにありたす。

停止しないでくださいUnity Procedural Maze Generationチュヌトリアルで䜿甚されおいる、より掗緎されたテクニックを詊しおください。

このチュヌトリアルを楜しんで、情報がお圹に立おば幞いです。私が衚珟する特別な感謝ゞャスパヌフリックのコヌディングのCatlike私を助けた圌の優れたチュヌトリアルのためには、私のプロゞェクトのためのデモを組み立おたす。

Source: https://habr.com/ru/post/J428796/


All Articles