自繪制執行個體

好處就是通過拖動,能實時看到模型變化,并且是執行個體化(可儲存)
整個結構是好的,構思也是好的,實作也實作了
網上例子還不少,就幾個三角面,乍看好像也沒啥作用,工作中也不會用到,面試官也不會問到
但這時創造自己3D引擎的第一步
掌握了這個例子,就懂的了如何建立三角面,頂點和UV
下面圖,有錯,請辯證檢視和了解
完整“優化”代碼會貼在最後
頂點優化
其實發現網上有2~3個部落格是抄這個代碼的,原來的代碼反而找不到了,
//一個國小生寫的。。。。。。MD(這方法會把自己的節點也算進去,會多了1+)。。。。。。。。。
//var ts = this.GetComponentsInChildren<Transform>();
//估計他自己也是抄網上, 然後實作不下去了
//(現在已經糾正)
改成:
var ts_len = transform.childCount;
未優化前的代碼有個謬誤就是坑了我很久,怎麼3個子節點會有4個頂點???
三角面“優化”
解決了上面的謬誤了,我們繼續
//var tris = new int[] { 0, 1, 2, 0, 1, 3, 1, 2, 3 };
改成
var tris = new int[] { 0, 1, 2, 0, 2, 3 };
這裡有2個原則需要知道:(我也是搞這個例子才懂的)
1.三角面按順時針繪制,相對的,逆時針繪制的是背面
2.頂點數和UV數1:1對應,但是三角面不是,如何确定一個模型外皮三角面??美術每天都幹這個,不了解原理也無所謂
3.不确定美術是不是很了解,但是程式是真的不了解
舉個栗子
如果 trangles = 0,1,2
如果三角面 trangles = 0,2,3 則透明,需要鏡頭轉到背面才能看到
回到上面的代碼:
//var tris = new int[] { 0, 1, 2, 0, 1, 3, 1, 2, 3 };
var tris = new int[] { 0, 1, 2, 0, 2, 3 };
第一句,無論鏡頭從哪個角度看,基本上不可能同時看到3個面(有點不合常人邏輯),對了解有3D世界有幫助,但入門困難
第二句,簡單的隆起的小山丘,解決
UV優化
最後我們再加上貼圖
好像5,6年前,UNITY就推薦用sharedMesh, sharedMaterial
不要問為什麼。。。。。
MeshFilter filter = this.GetComponent<MeshFilter>();
MeshRenderer render = this.GetComponent<MeshRenderer>();
var mesh = filter.sharedMesh;
最後,完整代碼:
/* 自定義Mesh繪制
*
* - 已添加貼圖
*
* created by Sidney Lu———————2020:
* CSDN:
* https://blog.csdn.net/avi9111/article/details/105747834
* GITEE:
* https://gitee.com/avi9111/UnityUtils
*
* 開發中:
* uv自動展開
* 貼圖列子
* 模型清單
* 自定義頂點數
* 儲存模型
*
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
public class GenMeshByGameObject : MonoBehaviour
{
public Material mat;
private int genCount = 4;
private void Awake()
{
FullFill(genCount);
}
private void OnEnable()
{
GetComponent<MeshRenderer>().sharedMaterial = mat;
}
public void FullFill() {
FullFill(genCount);
}
public void FullFill(int totalCount)
{
int count = totalCount - transform.childCount;
for (int i = 0; i < count; i++)
{
GameObject gen = new GameObject();
gen.name = "mesh" + (transform.childCount + 1);
gen.transform.SetParent(transform, false);
}
}
void OnDrawGizmos()
{
MeshFilter filter = this.GetComponent<MeshFilter>();
MeshRenderer render = this.GetComponent<MeshRenderer>();
var mesh = filter.sharedMesh;
//一個國小生寫的。。。。。。MD(這方法會把自己的節點也算進去,會多了1+)。。。。。。。。。
//var ts = this.GetComponentsInChildren<Transform>();
//估計他自己也是抄網上, 然後實作不下去了
//(現在已經糾正)
var ts_len = transform.childCount;
Vector3[] vers = new Vector3[ts_len];
for (int i = 0; i < ts_len; i++)
{
vers[i] = transform.GetChild(i).position;
}
//var tris = new int[] { 0, 1, 2, 0, 1, 3, 1, 2, 3 };
var tris = new int[] { 0, 1, 2, 0, 2, 3 };
//一個國小生還害我寫一大堆,下面這段代碼是錯誤的
//uv(頂點到貼圖的映射)數量 == vertex(頂點)數量,
//是以這兩兄弟必然需要是相等
//下下的代碼才是正确,而且是最簡單的
//var uvs = new Vector2[6];
//uvs[0] = new Vector2(0, 0);
//uvs[1] = new Vector2(1, 0);
//uvs[2] = new Vector2(1, 1);
//uvs[3] = new Vector2(0, 0);
//uvs[4] = new Vector2(1, 1);
//uvs[5] = new Vector2(0, 1);
var uvs = new Vector2[] {
new Vector2(0,0)
,new Vector2(1,1)
,new Vector2(0,1)
,new Vector2(1,0)};
// mesh.Clear();
mesh.vertices = vers;
mesh.triangles = tris;
mesh.uv = uvs;
mesh.RecalculateNormals();
mesh.RecalculateBounds();
//MeshCollider的作用是????
//this.GetComponent<MeshCollider>().sharedMesh = mesh;
// var uvs = new[] { };
filter.sharedMesh = mesh;
}
}
#if UNITY_EDITOR
[CustomEditor(typeof(GenMeshByGameObject))]
public class GenMeshByGameObjectInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (GUILayout.Button("Gen"))
{
GenMeshByGameObject _t = target as GenMeshByGameObject;
_t.FullFill();
}
}
}
#endif
謝謝閱讀