• Unity
  • Ficker angles bone with spawn hierarchy

  • تم التحرير
Related Discussions
...

Hi everyone,
We tried to achieve this smooth effect in the game by moving the mouse around the character:

To do that, we spawn hierarchy on Unity and make a script (based on the law of sines) that allows the character's bones to follow the mouse here is the script:

public class BoneAim
{
    [SerializeField]
    public string boneName;
    [SerializeField]
    public float min;
    [SerializeField]
    public float max;
}


private float boneRotation( BoneAim boneAim, Spine.Bone topBone)
    {
        /****************************************************************************
         * A: Wrist     * 
         * B: Head      * DistB = DirAC.magnitude (distance between wrist and target)
         * C: Target    * DistC = DirAB.magnitude (distance between bones)
         ****************************************************************************/
        //Bone
        Spine.Bone bone = skeleton.FindBone(boneAim.boneName);
        string name = boneAim.boneName;
        //bone.UpdateWorldTransform();
        
//World Positions: //wrist Vector3 A = bone.GetWorldPosition(this.transform); //Head Vector3 B = topBone.GetWorldPosition(this.transform); //target Vector3 C = GameManager.instance.getCursor().cursorPosition(); //Directions Vector3 dirAB = B - A; Vector3 dirAC = C - A; Vector3 dirBA = A - B; Vector3 dirBC = C - B; Vector3 dirCA = A - C; Vector3 dirCB = B - C; //Angles (original, debug only, we will change values after recalculate) float angleA = Vector2.Angle(dirAB, dirAC); float angleB = Vector2.Angle(dirBC, dirBA); float angleC = Vector2.Angle(dirCA, dirCB); /************* * RECALCULATING * *************/ //To calculate AngleC we need to knoe distB, distC and anlgeB //disB / sinB = distC / sinC // //sinC = disC * sinB / distB //after that-> anlgeA = 180 - angleB - angleC //Rot topBone (correct) angleB = getBoneWorldRotation(topBone); Vector2 dirB = angleToVector2(angleB); dirB.Normalize(); //Origanl head angle (angleB) that's the only angle we know angleB = Vector2.Angle(dirB, dirBA.normalized); float distB = dirAC.magnitude; float distC = dirAB.magnitude; float sinB = Mathf.Sin(angleB * Mathf.Deg2Rad); float sinC = distC * sinB / distB; //AngleC angleC = Mathf.Asin(sinC) * Mathf.Rad2Deg; //AngleA (world space) angleA = 180 - angleC - angleB; Debuggin.add(name, "angleA:" + angleA); //Exist the angle if (!float.IsNaN(angleA)) { float angleAOriginal = Vector3.Angle(dirAB, dirAC); //rotation += world andle - originalWorldAngle float angleRot = angleA - angleAOriginal; if (angleRot < boneAim.min) angleRot = boneAim.min; else if (angleRot > boneAim.max) angleRot = boneAim.max; bone.rotation += angleRot; } bone.UpdateWorldTransform(); return angleA; } private float getBoneWorldRotation(Spine.Bone bone) { float _rot = bone.WorldRotationX - 90; if (_rot < -180) _rot += 360; return _rot; } public static Vector2 angleToVector2(float degrees) { float rad = degrees * Mathf.Deg2Rad; return new Vector2(Mathf.Cos(rad), Mathf.Sin(rad)); }

But we don't know why, in the game seems like the character has some problem with the angles:

We want to rotate bones in a smooth way, here is our schedule:

Do you have any idea of what could have hapened?

Thanks


skeletonAnim.UpdateLocal += skeletonAnimation_UpdateWorld;

boneRotation is being called in "skeletonAnimation_UpdateWorld", that we added to UpdateLocal from skeletonAnimation.