一,需求

从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. Linux 内核中的 GCC 特性

    https://www.ibm.com/developerworks/cn/linux/l-gcc-hacks/ GCC 和 Linux 是出色的组合.尽管它们是独立的软件,但是 Linux 完全依靠 ...

  2. c#中的??运算符

    注意啦,c#中的??运算符是和?:运算符是不同的,这两者是有区别的. ??运算符称为null合并运算符,用于定义null值的类型和引用类型的默认值. 只当运算符的左操作数不为 null,此运算符将返回 ...

  3. 常见Linux命令(非文件操作)

    可见 http://man.linuxde.net/systemctl 非常详尽

  4. [Java基础] Java线程复习笔记

    先说说线程和进程,现代操作系统几乎无一例外地采用进程的概念,进程之间基本上可以认为是相互独立的,共享的资源非常少.线程可以认为是轻量级的进 程,充分地利用线程可以使得同一个进程中执行多种任务.Java ...

  5. MLP 之手写数字识别

    0. 前言 前面我们利用 LR 模型实现了手写数字识别,但是效果并不好(不到 93% 的正确率). LR 模型从本质上来说还只是一个线性的分类器,只不过在线性变化之后加入了非线性单调递增 sigmoi ...

  6. Chrome 控制台新玩法-向输出到console的文字加样式

    Chrome 控制台新玩法-向输出到console的文字加样式 有兴趣的同学可以文章最后的代码复制贴到控制台玩玩. Go for Code 在正常模式下,一般只能向console 控制台输出简单的文字 ...

  7. 流畅的python第三章字典和集合学习记录

    什么是可散列的数据类型 如果一个对象是可散列的,那么在这个对象的生命周期中,他的散列值是不变的,而且这个对象需要实现__hash__()方法.另外可散列对象还要有__qe__()方法.这样才能跟其他键 ...

  8. 使用node中的express解决vue-cli加载不到dev-server.js的问题

    在使用vue开发过程中,难免需要去本地数据地址进行请求,而原版配置在dev-server.js中,新版vue-webpack-template已经删除dev-server.js,改用webpack.d ...

  9. iOS 程序从开发完到上 AppStore 那点事儿

    收录待用,修改转载已取得腾讯云授权 一.账号体系 想要进行iOS开发,除了必备一台装有Mac OS X/Xcode的Mac开发机(iMac or MacBook)之外,还必须要有苹果开发者账号,只有拥 ...

  10. [Android Pro] service中显示一个dialog 或者通过windowmanage显示view

    转载: http://blog.csdn.net/huxueyan521/article/details/8954844 通过windowmananger来在窗口上添加view的时候,需要设置aler ...