I would like to rotate a head of a humanoid character given x, y, z rotation values using a script (without using any other object in the scene as "look" direction).
When setting-up the rigging of a Humanoid character (humanoid prefab --> Rig --> Animation Type: Humanoid --> Configure --> Muscles & Settings), you see the following interface: https://docs.unity3d.com/Manual/MuscleDefinitions.html
In this menu, under Head, you can drag a slider to move e.g. your humanoid head up and down. I want to achieve the same with a script, but I don't know how to do this.
This question never received a proper answer with example code: https://answers.unity.com/questions/824628/can-we-using-script-to-moving-the-muscles-in-unity.html
I presume I have to do something with HumanPose.muscles
(https://docs.unity3d.com/ScriptReference/HumanPose-muscles.html), however with the lack of code samples, I have no idea how to approach this.
Edit 3: This link has a code sample for HumanPose, but I didn't get it to work yet: https://forum.unity.com/threads/humanposehandler.430354/
How to get the head muscles of a humanoid character and rotate them by giving values through a script? (Or any other way how to rotate the head using head rotation values, without another object in the scene). Any help would be appreciated.
I receive a JSON formatted message from which I extract the radian values and change it into degrees:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Newtonsoft.Json.Linq; // JSON reader; https://assetstore.unity.com/packages/tools/input-management/json-net-for-unity-11347
public class HeadRotator : MonoBehaviour {
Quaternion rotation = Quaternion.identity;
// Radians to degree
float Rad2Degree = 180 / Mathf.PI;
// Human muscle stuff
HumanPoseHandler humanPoseHandler;
HumanPose humanPose;
Animator anim;
//Transform head;
// Use this for initialization
void Start () {
// get attached Animator controller
anim = GetComponent<Animator>();
//head = anim.GetBoneTransform(HumanBodyBones.Head);
//Debug.Log (head);
}
// Use JSON message to set head rotation and facial expressions;
// IEnumerator to run in main thread (needed for SetBlendShapeWeight)
public IEnumerator RequestHeadRotation(JObject head_pose)
{
// rotate head of character with received x, y, z rotations in radian
List<float> head_rotation = new List<float> ();
foreach (KeyValuePair<string, JToken> pair in head_pose) {
//Debug.Log(pair);
// store head rotation in degrees
head_rotation.Add(float.Parse(pair.Value.ToString())*Rad2Degree*10);
}
Debug.Log ("" + head_rotation[0] + ", " + head_rotation[1] + ", " + head_rotation[2]);
//Quaternion rotation = Quaternion.Euler(new Vector3(head_rotation[0], head_rotation[1], head_rotation[2]));
//Debug.Log ("" + rotation[0] + ", " + rotation[1] + ", " + rotation[2] + ", " + rotation[3]);
// head.Rotate (rotation);
// https://docs.unity3d.com/ScriptReference/Quaternion-eulerAngles.html
rotation.eulerAngles = new Vector3 (head_rotation[0], head_rotation[1], head_rotation[2]);
// Animator.GetBoneTransform()
anim.SetBoneLocalRotation(HumanBodyBones.Head, rotation);
yield return null;
}
}
3.208564, 0.4583662, 0.1145916
0.0280001, 0.003970424, 0.0008876149, 0.9995997
I don't really know well how to set either the head bone or the muscles. Most examples provide only a snippet of the code, so I'm struggling in figuring out how it works.
Edit 2: I feel I'm getting close, but anim.SetBoneLocalRotation(HumanBodyBones.Head, rotation);
seems to get ignored.
Edit 4: I put on Github a simple version of my head rotation attempt: https://github.com/NumesSanguis/Basic-Unity-Head-Rotation
After testing for a while, I figured it out.
animator
to IK
Pass.SetBoneLocalRotation
inside OnAnimatorIK
method. You can know more about this method here: https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnAnimatorIK.html using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HeadRotator : MonoBehaviour
{
public Vector3 rot = new Vector3(20, 30, 10);
Animator anim;
// Bone stuff
Transform head;
// !!! Head bone rotation approach !!!
void Start () {
// get attached Animator controller
anim = GetComponent<Animator>();
head = anim.GetBoneTransform(HumanBodyBones.Head);
}
void OnAnimatorIK (int layerIndex) {
print ("OnAnimatorIK - running");
anim.SetBoneLocalRotation(HumanBodyBones.Head, Quaternion.Euler(rot));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With