c# - Unity3d - How to make method calling from another class that belongs to another game object efficiently -
this continuity question.
what want here create program calculate score based on 3d model's movement , show change of model's color.
but since model's movement recorder, score calculation, , coloring different classes attached on different game object, need make them connect each other work together.
i come solution below snippet, system got laggy , freezing. new unity world, ask guys, there method more efficient kind of job?
here code structure in detail, problem involving 3 different class calling each other (all attached different game object)
1) bonehighlighter.cs
to re-coloring on model based on script previous question
//declare skinnedmeshrenderer public skinnedmeshrenderer smr; //initialization //previously put initialization on start(), try put on awake() make initialization 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]; (int j= 0; j<bones.length; j++) { var idx = getboneindex (bones [j]); (int = 0; < 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
this call highlight()
function, class return float number 0-1 determine intensity of color. how call highlight()
function
//declare highlighter class public variable //drag & drop gameobject containing bonehighlighter.cs property inspector public bonehighlighter highlighter = null; //calculate score , pass highlight() function private void calculatescore(int data) { . . highlighter.highlight(highlightedregion, cost); } //get data other game object public void getdata(frame frame) { calculatescore((int)skeleton.righthand); }
3) manager.cs
this class used 3d model data each frame , pass comparator.cs score calculation
public comparator comparatorclass = null; void update () { . . comparatorclass.getdata(frame); }
1) first problem highlight implementation. line mesh.colors32 = colors;
should not inside for. way assign mesh.colors32 multiple times, matters last time assign it, others overwritten. should be:
(int j= 0; j<bones.length; j++) { var idx = getboneindex (bones [j]); (int = 0; < 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; // finally, once
making coroutine suggested here not needed, (and make things worse).
2) primary problem call highligh
on each update
. highlight
not light function since might need access objects inside gpu memory when setting mesh colors. update
called on each frame. don't have highligh
on every frame - once highlighted, remain highlighted until "unhighlighted". might want call highlight
, if changed.
a simple way remember highlighted on previous frame, , highlight if changed. example, highlighter object may this:
//declare skinnedmeshrenderer public skinnedmeshrenderer smr; //initialization //previously put initialization on start(), try put on awake() make initialization bit sooner void awake () { if (smr == null) smr = getcomponent<skinnedmeshrenderer>(); smr.sharedmesh = (mesh)instantiate(smr.sharedmesh); } // remember index , ratio used last time highlight. private int previndex = -1; private int prevratio = -1; // change vertex colors highlighting given bone public void highlight(int index,double ratio = 1 ) { // if nothing changed, no need highligh again - // highlighted. break function execution. if (index == previndex && ratio == prevratio) return; 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]; (int j= 0; j<bones.length; j++) { var idx = getboneindex (bones [j]); (int = 0; < 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); } //debug.log("bone index:\t"+bones[j].tostring()); } mesh.colors32 = colors; // finally, once } else debug.log("smr null"); }
Comments
Post a Comment