C# UNITY仅更改三维模型的某些部分';s颜色

C# UNITY仅更改三维模型的某些部分';s颜色,c#,unity3d,3d,modeling,3d-modelling,C#,Unity3d,3d,Modeling,3d Modelling,我是unity3D的新手,我想问一个问题 我有一个3D人体模型(默认的unity模型),它具有层次化的骨骼结构 我想在这里实现的是,当我按下某个触发器时,我想给它的一个肢体涂上不同的颜色(只是它的一个肢体)。这是我想要达到的目标的例证 我真的对此一无所知,因为我大约3个月前才开始学习Unity,所以我真的需要你的帮助,这是我的渲染器的属性,如果它有帮助的话 如果你是初学者,你必须读一些书。在更改某些内容之前,请确保完全了解模型设置: 此辅助对象有1个单个网格(三维模型) 此模型由1种材质渲染

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

我想在这里实现的是,当我按下某个触发器时,我想给它的一个肢体涂上不同的颜色(只是它的一个肢体)。这是我想要达到的目标的例证

我真的对此一无所知,因为我大约3个月前才开始学习Unity,所以我真的需要你的帮助,这是我的渲染器的属性,如果它有帮助的话


如果你是初学者,你必须读一些书。在更改某些内容之前,请确保完全了解模型设置:

  • 此辅助对象有1个单个网格(三维模型)
  • 此模型由1种材质渲染(蒙皮网格渲染器仅附着1种材质)
  • 此材质具有基础RGBA纹理,可为模型着色。现在这里有一个陷阱:要在3D模型上映射2D纹理,我们使用UV映射。UV贴图是一种桥梁,将三维模型上的每个顶点连接到平面上的二维坐标。在3D中我们称它们为顶点,在2D中我们称它们为-UV。因此,当您在2D平面上(在photoshop、gimp等中)为一个UV周围的区域着色时,相应的顶点将在网格上着色。谷歌UV映射获取更多信息。注意:不能在Unity中进行UV映射(除非通过脚本),通常在外部3D建模软件中进行
  • 最后,在完成所有的谷歌搜索后,你可以切换到你的任务。到现在为止,您可能已经了解需要修改模型的纹理。您需要找到模型的手映射到哪里,然后使用脚本更改该区域的颜色。你和我一起做
还有另一种解决方案需要优化,它的编程性较低,逻辑性更强,但方式粗糙:

  • 将该模型导入三维建模软件
  • 分离手臂,但确保其仍由骨架控制
  • 将模型导入Unity
  • 为手臂制作新材质时,可以复制现有材质(通常为更改视觉特性的对象制作单独的材质)
  • 复制RGBA纹理并在图像编辑软件中对其进行去饱和
  • 将此复制纹理指定给复制材质的颜色槽,并将复制材质指定给手臂模型
  • 手臂现在应该是灰度的,因此可以通过更改材质颜色来更改其颜色

我只是想补充一点,也许有一种更简单的方法可以实现您想要的功能。这是unity中常用的工具,用于实时在网格曲面上绘制各种效果,例如弹孔。使用相同的原理,可以高亮显示网格的某些区域。你可以把投影仪想象成手电筒,它的光线照射到的任何东西都会改变它的纹理。标准资产/效果下有一些投影仪示例。你可能想从那里开始

要创建projectror,请创建一个空的游戏对象=>Add Component=>Projector

编辑

你可能想尝试的另一个想法是使用。网格的每个顶点除坐标外还包含一个颜色参数,可通过着色器访问该参数。因此,可以更改特定顶点集的颜色以高亮显示它们。这里有两点你必须注意:

1) 大多数着色器选择忽略顶点颜色,精灵着色器除外。您将需要一个自定义着色器,例如

2) 您需要知道到底要高亮显示哪些顶点。你能做的就是迭代。例如,如果要选择手臂,则需要为手臂骨骼索引选择权重>1的所有顶点。你如何找到手臂骨骼指数?此索引对应于中的索引。或者只需选择一些你确定属于手臂的顶点,并查看其骨骼权重即可找到索引

这里是一个基于选定骨骼索引更改顶点颜色的示例脚本。将其附加到SkindMeshRenderer(通常是第二级层次结构对象):

使用UnityEngine;
使用系统集合;
公共类BoneHighlighter:单行为{
公共颜色32 highlightColor=Color.red;
公共颜色32 regularColor=Color.white;
公众皮肤病;
//只是为了示范
公共转换骨;
私有骨;
//查找给定骨骼变换的骨骼索引
int GetBoneIndex(变换骨骼){
Assert(smr!=null);
var-bones=smr.bones;
对于(int i=0;i0)
总和+=权重[i]。权重0;
如果(权重[i].boneIndex1==idx&&weights[i].weight1>0)
总和+=权重[i]。权重1;
如果(权重[i].boneIndex2==idx&&weights[i].weights 2>0)
总和+=权重[i]。权重2;
如果(权重[i].boneIndex3==idx&&weights[i].weights 3>0)
总和+=权重[i]。权重3;
colors[i]=Color32.Lerp(regularColor、highlightColor、sum);
}
mesh.colors32=颜色;
}
void Start(){
//如果未明确指定SkindMeshRenderer,请尝试查找一个
如果(smr==null)smr=GetComponent();
//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);
        }
    }
}