UNITY-只改变3D模型的某一部分颜色。

问题描述 投票:4回答:2

我真的是unity3D的新手,我想问一个问题我有一个3D人体模型(一个默认的unity模型),它有一个分层的骨骼结构。

我想在这里实现的是,当我按下某些触发器时,我想给它的一个肢体涂上不同的颜色(只是它的一个肢体)。这就是我想实现的功能的说明。

enter image description here

我对这个真的是毫无头绪,因为我3个月前才开始学习Unity,所以我真的需要你的帮助,这是我渲染器的属性,如果对你有帮助的话。

enter image description here

c# unity3d 3d modeling 3d-modelling
2个回答
5
投票

我只是想补充一下,可能有一个更简单的方法来实现你想要的使用 投影机. 这是unity中常用的工具,用于在网格表面实时绘制各种效果,比如弹孔。使用同样的原理,你可以突出网格的某些区域。你可以把投影仪想象成手电筒,它的光线照射到的所有东西都会改变它的纹理。在标准资产效果下有一些投影仪的例子。你可能想从那里开始。

要创建一个投影仪,创建一个空的游戏对象 => Add Component => Projector。

编辑

您可能想尝试的另一个想法是使用 顶点颜色. 网格的每个顶点除了坐标外,还包含一个颜色参数,可以通过shader访问。因此,你可以改变特定顶点集的颜色来突出它们。这里有2点你要注意。

1)大多数着色器选择忽略顶点颜色,除了精灵着色器。你需要一个自定义的着色器,如 这个.

2) 你需要知道你到底要高亮哪些顶点。你可以做的是迭代到 Mesh.boneWeights. 例如,如果你想选择一个手臂,你需要的是所有具有重量> 1的顶点的臂骨指数。如何找到臂骨指数?这个指数对应于 SkinnedMeshRenderer.bones。. 或者只需选择一些你确定属于手臂的顶点,然后查看它的骨骼权重来找到索引。

这里有一个根据选定的骨骼指数来改变顶点颜色的示例脚本,将它附加到你的SkinedMeshRenderer(通常是第二层的层次结构对象)上。将它附加到你的SkinnedMeshRenderer(通常是一个二级层次结构对象)。

using UnityEngine;
using System.Collections;

public class BoneHiglighter : MonoBehaviour {

    public Color32 highlightColor = Color.red;
    public Color32 regularColor = Color.white;

    public SkinnedMeshRenderer smr;

    // Just for sake of demonstration
    public Transform bone;
    private Transform prevBone;


    // Find bone index given bone transform
    int GetBoneIndex(Transform bone) {
        Debug.Assert(smr != null);
        var bones = smr.bones;

        for (int i = 0; i < bones.Length; ++i) {
            if (bones[i] == bone) return i;
        }

        return -1;
    }

    // Change vertex colors highlighting given bone
    void Highlight(Transform bone) {
        Debug.Assert(smr != null);
        var idx = GetBoneIndex(bone);
        var mesh = smr.sharedMesh;
        var weights = mesh.boneWeights;
        var colors = new Color32[weights.Length];

        for (int i = 0; i < colors.Length; ++i) {
            float sum = 0;
            if (weights[i].boneIndex0 == idx && weights[i].weight0 > 0)
                sum += weights[i].weight0;
            if (weights[i].boneIndex1 == idx && weights[i].weight1 > 0)
                sum += weights[i].weight1;
            if (weights[i].boneIndex2 == idx && weights[i].weight2 > 0)
                sum += weights[i].weight2;
            if (weights[i].boneIndex3 == idx && weights[i].weight3 > 0)
                sum += weights[i].weight3;

            colors[i] = Color32.Lerp(regularColor, highlightColor, sum);
        }

        mesh.colors32 = colors;

    }

    void Start() {
        // If not explicitly specified SkinnedMeshRenderer try to find one
        if (smr == null) smr = GetComponent<SkinnedMeshRenderer>();
        // SkinnedMeshRenderer has only shared mesh. We should not modify it.
        // So we make a copy on startup, and work with it.
        smr.sharedMesh = (Mesh)Instantiate(smr.sharedMesh);

        Highlight(bone);
    }

    void Update() {
        if (prevBone != bone) {
            // User selected different bone
            prevBone = bone;
            Highlight(bone);
        }
    }
}

请看一个示例项目。https:/www.dropbox.comsyfoqo44bubcr48sHighlightBone.zip?dl=0

演示。http:/jolly-squirrel.droppages.combonesindex.html。 - 点击身体部位可以看到它们的亮点。


0
投票

如果你是一个初学者,你必须做一些阅读。在改变一些东西之前,请确保你完全理解模型设置。

  • 这个工人有一个单一的网格(3D模型)。
  • 这个模型是由1个材质渲染的(蒙皮网格渲染器只附加了1个材质)
  • 这个材质有一个基本的RGBA纹理,它为你的模型着色。现在有一个问题:为了在3D模型上映射2D纹理,我们使用UV映射。UV贴图是一种桥梁,它将3D模型上的每个顶点与平面上的一个2D坐标联系起来。在3D中我们称它们为顶点,在2D上我们称之为--UV。因此,当你在2D平面上给一个UV周围的区域着色时(在Photoshop、Gimp等),相应的顶点就会在网格上着色。Google UV贴图可以获得更多信息。注意:你不能在Unity中做UV贴图(除非通过脚本),它通常是在外部3D建模软件中完成的。
  • 最后,在完成了所有的google之后,你可以切换到你的任务。你现在可能已经明白,你需要修改模型的纹理。你需要找到你的模型的手被映射到哪里,然后用脚本改变该区域的颜色。你可以用 Texture2D.GetPixels()SetPixels().

还有一种解决方法,不那么程式化,更符合逻辑,但方式粗糙,需要优化。

  • 把这个模型导入到一个3D建模软件中
  • 分离手臂,但要确保它仍然是用骨架控制的。
  • 将模型导入到Unity中
  • 为手臂制作一个新的材质,你可以复制现有的材质(为改变视觉属性的对象单独制作材质是一种常见的做法)。
  • 复制你的RGBA纹理,并在图像编辑软件中对其进行去饱和处理。
  • 将这个复制的纹理分配到复制材质的颜色槽中,并将复制的材质分配到手臂模型中。
  • 现在手臂应该是灰度的,所以你可以通过改变材质颜色来改变它的颜色。
© www.soinside.com 2019 - 2024. All rights reserved.