一,需求

从fbx载入的模型是不可以在unity里编辑的。

我有一人特殊的需求就是想在unity里为mesh的各顶点K动画。

于是需要自己实现一个可编辑(其实只是顶点可以拖动)的mesh。

二,思路

首先由导入的mesh复制一个新mesh,并将原mesh替换掉,这样是为了以后编辑过程不会破坏原mesh,然后就没有原mesh的事儿了。

假设mesh是一个立方体,则其mesh.vertices会有36个元素,mesh.triangles有12个元素。

我们要创建8个gameObject表示立方体的8个顶点gameObject,并根据mesh.vertices的坐标值设定顶点gameObject的localPosition(注意是localPosition而不是position),并且还要找出各顶点gameObject对象mesh.vertcies中的哪些元素。因为一共有8个顶点gameObject,但mesh.vertices有36个元素,所以一个gameObject对应多个元素。

三,unity里实现

1,创建一个gameObject,命句为editableMesh,并添加Mesh Filter和Mesh Renderer,Mesh Filter中添加模型mesh(例如从3dmax或blender中导出的模型)。

2,为editableMesh节点添加子节点vertexObjTemplate并将勾去掉使其变成Active==false状态,其上挂脚本vertexobjControl.cs:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class vertexObjControl : MonoBehaviour {
    public List<int> m_vIDList=new List<int>();
}

3,为editableMesh节点添加脚本convertmeshToEditableMesh.cs

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Assertions.Must;
[ExecuteInEditMode]
public class convertMeshToEditableMesh : MonoBehaviour {
    private GameObject m_vertexObjs;
    private GameObject m_vertexObjTemplate;
    void Awake(){
        m_vertexObjTemplate=transform.FindChild("vertexObjTemplate").gameObject;

CreateReplaceMeshFromOriginMesh ();
    }
    void Update(){
        updateMeshVertex ();
    }
    void updateMeshVertex(){
        int vertexCount = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertexCount;
        Vector3[] vertices = new Vector3[vertexCount] ;

int vertexObjCount = m_vertexObjs.transform.childCount;
        for (int i=0; i<vertexObjCount; i++) {
            GameObject vobj=m_vertexObjs.transform.GetChild(i).gameObject;
            Vector3 vobjPos=vobj.transform.localPosition;
            int nVID=vobj.GetComponent<vertexObjControl>().m_vIDList.Count;
            for(int j=0;j<nVID;j++){
                int vID=vobj.GetComponent<vertexObjControl>().m_vIDList[j];
                vertices[vID]=vobjPos;
            }
        }
        gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices = vertices;

gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateNormals();
        gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateBounds();
    }
    void CreateReplaceMeshFromOriginMesh()
    {
        //if vertexObjs is not created, create it
        Transform vertexObjsTransform=transform.FindChild("vertexObjs");
        if (vertexObjsTransform == null) {
            m_vertexObjs = new GameObject ();
            m_vertexObjs.name = "vertexObjs";
            m_vertexObjs.transform.SetParent (gameObject.transform);
        } else {
            m_vertexObjs=vertexObjsTransform.gameObject;
        }

//if mesh not replaced, replace it
        if (gameObject.GetComponent<MeshFilter> ().sharedMesh.name != "replaceMesh") {
            Mesh replaceMesh = Instantiate (gameObject.GetComponent<MeshFilter> ().sharedMesh) as Mesh;
            replaceMesh.name = "replaceMesh";
            gameObject.GetComponent<MeshFilter> ().sharedMesh = replaceMesh;
        }

//if vobjs not generated, generate vobjs from replaved mesh
        if (m_vertexObjs.transform.childCount == 0) {
            int vertexCount = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertexCount;
            List<bool> list_isVIDHasAddedToVObj = new List<bool> ();
            for (int i=0; i<vertexCount; i++) {
                list_isVIDHasAddedToVObj.Add (false);
            }
            for (int vID=0; vID<vertexCount; vID++) {
                if (list_isVIDHasAddedToVObj [vID]) {
                    continue;
                }
                //add vID of current vertex to existing vertexObj

Vector3 vPos = gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices [vID];
                int vertexObjCount = m_vertexObjs.transform.childCount;
                for (int vobjID=0; vobjID<vertexObjCount; vobjID++) {
                    GameObject vobj = m_vertexObjs.transform.GetChild (vobjID).gameObject;
                    Vector3 vobjPos = vobj.transform.localPosition;
                    if (vPos == vobjPos) {
                        //add vID to vobj
                        vobj.GetComponent<vertexObjControl> ().m_vIDList.Add (vID);
                        list_isVIDHasAddedToVObj [vID] = true;
                    }
                }
                if (list_isVIDHasAddedToVObj [vID]) {//vID has added to existing vobj
                    //do nothing

} else {//no existing vobj for vID to add to
                    //create new vobj, and add vID to it
                    GameObject vobj = Instantiate (m_vertexObjTemplate);
                    vobj.SetActive (true);
                    vobj.name = "vobj_" + m_vertexObjs.transform.childCount;
                    vobj.transform.SetParent (m_vertexObjs.transform);
                    vobj.transform.localPosition = vPos;
                    vobj.GetComponent<vertexObjControl> ().m_vIDList.Add (vID);
                    list_isVIDHasAddedToVObj [vID] = true;
                }

}
        }
        gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateNormals();
        gameObject.GetComponent<MeshFilter> ().sharedMesh.RecalculateBounds();
    }
}

然后就可以在编辑器里移动mesh的顶点或给顶点K动画了。

----补充:

以上是通用的代码,可将任何mesh转成可编辑(只是移动顶点)的。

如果只想做一个可编辑的四边形面片,可以像下面这样简单实现:

1,创建一个gameObject命名为editableQuad。为editableQuad创建子节点vertexObjs。再为vertexObjs依次创建子节点vertexObj_0,vertexObj_1,vertexObj_2,vertexObj_3(按顺序排列)。

2,再为editableQuad添加脚本editableQuadControl.cs:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.Assertions.Must;
[ExecuteInEditMode]
public class editableQuadControl : MonoBehaviour {
    private GameObject vertexObjs;
    void Awake(){

vertexObjs=transform.FindChild("vertexObjs").gameObject;
        int childCount = vertexObjs.transform.childCount;
        int n = 4;

for (int i=0; i<n; i++) {
            if(i>=childCount){
                GameObject vertexObj=new GameObject ();
                vertexObj.name="vertexObj_"+i;
                vertexObj.transform.SetParent(vertexObjs.transform);
                vertexObj.transform.localPosition=Random.insideUnitSphere;
            }
        }
        gameObject.GetComponent<MeshFilter> ().mesh = CreateMesh ();
    }
    void Update(){
        updateMeshVertex ();
    }
    void updateMeshVertex(){
        Vector3 vLU = vertexObjs.transform.GetChild(0).localPosition;
        Vector3 vLD = vertexObjs.transform.GetChild(1).localPosition;
        Vector3 vRU = vertexObjs.transform.GetChild(2).localPosition;
        Vector3 vRD = vertexObjs.transform.GetChild(3).localPosition;
        gameObject.GetComponent<MeshFilter> ().sharedMesh.vertices = new Vector3[]{vLD,vLU,vRU,vRD};
    }
    Mesh CreateMesh()
    {
        Mesh m = new Mesh();
        m.name = "ScriptedMesh";
        //note: unity is left-hand system
        Vector3 vLU = vertexObjs.transform.GetChild(0).localPosition;
        Vector3 vLD = vertexObjs.transform.GetChild(1).localPosition;
        Vector3 vRU = vertexObjs.transform.GetChild(2).localPosition;
        Vector3 vRD = vertexObjs.transform.GetChild(3).localPosition;
        m.vertices = new Vector3[] {
            vLD,//LD
            vLU,//LU
            vRU,//RU
            vRD//RD
        };
        m.uv = new Vector2[] {
            new Vector2 (0, 0),
            new Vector2 (0, 1),
            new Vector2 (1, 1),
            new Vector2 (1, 0)
        };
        m.triangles = new int[] { 0, 1, 2, 0, 2, 3};
        m.RecalculateNormals();
        m.RecalculateBounds();
        return m;
    }
}

unity, editable mesh的更多相关文章

  1. Unity中Mesh分解与边缘高亮加上深度检测

    一个比较简单的需求,不过遇到些坑,记录下. 房间有多个模型,每个模型可能多个SubMesh,点击后,需要能具体到是那个SubMesh,并且在这个SubMesh上显示边缘高光,以及能个性这单个SubMe ...

  2. Unity的Mesh压缩:为什么我的内存没有变化?

    0x00 前言 最近和朋友聊天,谈到了Mesh的内存优化问题,他发现开启Model Importer面板上的Mesh Compression选项之后,内存并没有什么变化.事实上,期望开启Mesh Co ...

  3. 关于Unity中Mesh网格的详解

    3D模型 通过3D建模软件所建出来的点和面,如以三角形为主的点和面,比如人的脑袋一个球,就是由各种各样的三角形组成的点和面. 点和面以及纹理坐标都是通过3D建模软件建模出来的. Unity会帮我们把模 ...

  4. unity, 获取mesh名称

    正确的获取mesh名称的方法: MeshFilter meshFilter=node.GetComponent<MeshFilter>();    string meshName=mesh ...

  5. unity中mesh属性的uv坐标讨论

    http://blog.sina.com.cn/s/blog_427cf00b0102vp0j.html 之前在做连连看游戏中,也用到贴图坐标,当时我们讲到,不管是平铺(Tiling)还是偏移(Off ...

  6. Unity中用Mesh画一个圆环

    Probuider 前几天在做一个小项目的时候,用到了Unity自带的一个包ProBuilder其中的Arch生成1/4圆. 挺好玩的,可以在直接Unity中根据需要用Mesh定制生成图形,而不用建模 ...

  7. unity替换mesh测试

    直接替换SkinnedMeshRender的Mesh,实现所谓断肢效果(不过最近发现,绑定多mesh似乎更好实现这样的效果.有时间准备写一篇): 只要不改变两个Mesh原始文件的层级,就不会出现权重的 ...

  8. Unity中用Mesh画一个圆环(二)

    中目标-生成完整面 在之前的内容中我们已经成功生成了一个面,接下来我们要生成剩下的面就很容易了. 我们把之前生成的面当作顶面,接着我们来生成底面. 还记得前面说过\(\color{#1E90FF}{D ...

  9. Unity 绘制Mesh线条

    using UnityEngine; using System.Collections; using System.Collections.Generic;   public struct Segme ...

随机推荐

  1. CDOJ 1281 暴兵的卿学姐 构造题

    暴兵的卿学姐 题目连接: http://acm.uestc.edu.cn/#/problem/show/1281 Description 沈宝宝又和卿学姐开始玩SC2了! 自从沈宝宝学会新的阵型后,就 ...

  2. mysql远程表/视图-应用

    Date :20140213Auth: Jin参考http://blog.sina.com.cn/s/blog_757b0e130101erl5.htmlhttp://dev.mysql.com/do ...

  3. php中文件上传需要注意的几点

    1.首先要开启php.ini中的文件上传,打开php.ini 配置文件,查找 File Uploads ,在这个区域有以下3个选项: ;;;;;;;;;;;;;;;; ; File Uploads ; ...

  4. NHibernate 操作视图 第十三篇

    在NHibernate中,可以把视图当表一样操作,只需要记住一点就是,视图是只读的,因此映射实体的setter应该改为protected. 新建一个视图如下: 持久化类: public class C ...

  5. Openshift部署Zookeeper和Kafka

    部署Zookeeper github网址 https://github.com/ericnie2015/zookeeper-k8s-openshift 1.在openshift目录中,首先构建imag ...

  6. 使用神经网络识别手写数字Using neural nets to recognize handwritten digits

    The human visual system is one of the wonders of the world. Consider the following sequence of handw ...

  7. AWR Report 关键参数详细分析

    WORKLOAD REPOSITORY report for DB Name DB Id Instance Inst num Startup Time Release RAC CALLDB 12510 ...

  8. 18.并发类容器MQ

    package demo7.MQ; public class QueueData { private int id; private String name; private String taskC ...

  9. @RestController和@Controller的差异

    SpringMVC现在使用越来越普及,在使用注解写控制器中发现,需要控制器页面跳转时,需要对类注解为@Controller,而此时,使用freemarker时,在类中写的restful接口会报cann ...

  10. python numpy学习记录

    numpy是一个python和矩阵相关的库,在机器学习中非常有用,记录下numpy的基本用法 numpy的数组类叫做ndarray也叫做数组,跟python标准库中的array.array不同,后者只 ...