这是从这个question的连续性。Unity3d - 如何使另一个类别有效地属于另一个游戏对象的方法有效
我想在这里做的是创建一个程序来计算基于3D模型的运动的一些分数,并将其显示为模型颜色的变化。
但是,由于模型的移动记录器,分数计算和着色来自不同类别的游戏对象,我需要让它们互相连接才能一起工作。
我想出了类似下面的代码片段的解决方案,但系统得到了延迟和冻结。我是Unity新手,所以我问你们,有没有更有效率的方法来完成这种工作?
下面是详细我的代码结构,所以这个问题是涉及3个不同的类相互调用(所有连接到不同的游戏对象)
1)BoneHighlighter.cs
做一些重新根据先前的问题
//declare SkinnedMeshRenderer
public SkinnedMeshRenderer smr;
//initialization
//previously put the initialization on Start(), but I try to put it on Awake() to make the initialization a bit sooner
void Awake()
{
if (smr == null) smr = GetComponent<SkinnedMeshRenderer>();
smr.sharedMesh = (Mesh)Instantiate(smr.sharedMesh);
}
// Change vertex colors highlighting given bone
public void Highlight(int index,double ratio = 1)
{
Transform[] bones = null;
switch (index)
{
case (int)Skeleton.Head: bones = head; break;
case (int)Skeleton.UpperBody: bones = upperBody; break;
case (int)Skeleton.LowerBody: bones = lowerBody; break;
case (int)Skeleton.RightUpperArm: bones = upperArmRight; break;
case (int)Skeleton.RightLowerArm: bones = lowerArmRight; break;
case (int)Skeleton.RightHand: bones = handRight; break;
case (int)Skeleton.LeftUpperArm: bones = upperArmLeft; break;
case (int)Skeleton.LeftLowerArm: bones = lowerArmLeft; break;
case (int)Skeleton.LeftHand: bones = handLeft; break;
case (int)Skeleton.RightUpperLeg: bones = upperLegRight; break;
case (int)Skeleton.RightLowerLeg: bones = lowerLegRight; break;
case (int)Skeleton.RightFoot: bones = footRight; break;
case (int)Skeleton.LeftUpperLeg: bones = upperLegLeft; break;
case (int)Skeleton.LeftLowerLeg: bones = lowerLegLeft; break;
case (int)Skeleton.LeftFoot: bones = footLeft; break;
default: break;
}
//Debug.Assert(smr != null);
if (smr != null)
{
var mesh = smr.sharedMesh;
var weights = mesh.boneWeights;
var colors = new Color32[weights.Length];
var sums = new float[weights.Length];
for (int j= 0; j<bones.Length; j++)
{
var idx = GetBoneIndex (bones [j]);
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;
sums [i] += sum;
colors [i] = Color32.Lerp (regularColor, highlightColor, sums [i] * (float)ratio);
mesh.colors32 = colors;
}
//Debug.Log("bone index:\t"+bones[j].ToString());
}
}
else Debug.Log("smr null");
}
2)Comparator.cs
脚本-coloring型号这就是我所说的Highlight()
函数,这个类将返回浮点数0-1来确定颜色的强度。这是我如何调用Highlight()
功能
//declare highlighter class as public variable
//drag & drop GameObject containing BoneHighlighter.cs from property inspector
public BoneHighlighter highlighter = null;
//calculate a score and pass it to highlight() function
private void calculateScore(int data)
{
.
.
highlighter.Highlight(highlightedRegion, cost);
}
//get the data from other game object
public void GetData(Frame frame)
{
calculateScore((int)Skeleton.RightHand);
}
3)Manager.cs
该类用于获得三维模型数据的每个帧,并把它传递给Comparator.cs用于分数计算
public Comparator comparatorClass = null;
void Update()
{
.
.
comparatorClass.GetData(frame);
}
谢谢您的回答,是的,第一个是我不好,我固定它,它的工作速度快了很多。对于第二个问题,我认为你是对的,但我怀疑通过保存我以前的状态可以解决问题,因为每一帧的比例都会发生很大的变化。我想出了几个想法,例如,在初始化时映射网格,所以我已经存储了哪个网格对应于每个骨骼,并且仅在这些网格之间进行迭代,而不是搜索整个网格。也许我会每5/10帧做一次突出显示,以使其更快 – Richard