Unity 3D: mueve los músculos de la cabeza humanoide usando un script
– UnityAssets3Free
hola , me llamo kein y para hoy os traigo
nueva pregunta curiosa
Meta
Me gustaría rotar la cabeza de un personaje humanoide con valores de rotación x, y, z usando un script (sin usar ningún otro objeto en la escena como la dirección de «mirada»).
Lo que quiero hacer
Al configurar el rigging de un personaje humanoide (prefabricado humanoide –> Equipo –> Tipo de animación: Humanoide –> Configurar –> Músculos y ajustes), verá la siguiente interfaz: https://docs.unity3d.com/Manual/Definiciones musculares.html
En este menú, debajo de Cabeza, puede arrastrar un control deslizante para mover, por ejemplo, su cabeza humanoide hacia arriba y hacia abajo. Quiero lograr lo mismo con un guión, pero no sé cómo hacerlo.
Recursos
Esta pregunta nunca recibió una respuesta adecuada con código de muestra: https://respuestas.unity.com/questions/824628/can-we-using-script-to-moving-the-muscles-in-unity.html
Supongo que tengo que hacer algo con HumanPose.muscles
(https://docs.unity3d.com/ScriptReference/HumanPose-muscles.html), sin embargo, con la falta de ejemplos de código, no tengo idea de cómo abordar esto.
editar 3: Este enlace tiene un ejemplo de código para HumanPose, pero todavía no he podido hacerlo funcionar: https://foro.unity.com/threads/humanposehandler.430354/
Pregunta
¿Cómo obtener los músculos de la cabeza de un personaje humanoide y rotarlos dando valores a través de un script? (O cualquier otra forma de rotar la cabeza usando los valores de rotación de la cabeza, sin ningún otro objeto en la escena). Cualquier ayuda sería apreciada.
Edición 1 y 2: código de muestra
Me sale un mensaje en formato JSON del cual extraigo los valores en radianes y los cambio en grados:
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;
- Datos de rotación de la cabeza:
3.208564, 0.4583662, 0.1145916
- Datos del cuaternión:
0.0280001, 0.003970424, 0.0008876149, 0.9995997
Realmente no estoy seguro de cómo definir el hueso de la cabeza o los músculos. La mayoría de los ejemplos solo proporcionan un fragmento de código, por lo que estoy luchando por descubrir cómo funciona.
editar 2: Siento que me estoy acercando, pero anim.SetBoneLocalRotation(HumanBodyBones.Head, rotation);
parece ser ignorado.
Editar 4: puse en Github una versión simple de mi intento de rotación de la cabeza: https://github.com/NumesSanguis/Basic-Unity-Head-Rotación
3 respuestas 3
Después de probar durante un tiempo, lo descubrí.
- Primero, establezca el
animator
porIK
Pasar.
- así que usa
SetBoneLocalRotation
en el interiorOnAnimatorIK
método. Puedes aprender más sobre este método aquí: https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnAnimatorIK.html
El siguiente es el código modificado que funcionó para mí.
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));
¡Gracias a @ZayedUpal, la rotación de los huesos de la cabeza está funcionando y gracias a un amigo que establece valores musculares también funciona!
El proyecto completo de Unity 3D para ambas opciones se puede encontrar aquí: https://github.com/NumesSanguis/Basic-Unity-Head-Rotación
Fragmento de código del enfoque de valores musculares:
// !!! Human Pose approach !!!
void Start ()
// https://forum.unity.com/threads/humanposehandler.430354/
// get attached Animator controller
anim = GetComponent<Animator>();
// run this if you want the indexes to muscles on your character
LookUpMuscleIndex();
// TODO keeping body above plane
//Vector3 current_position = transform.position;
// get human pose handler
humanPoseHandler = new HumanPoseHandler(anim.avatar, transform);
// get human pose
humanPose = new HumanPose();
// TODO keeping body above plane
//humanPose.bodyPosition = current_position;
// reference pose to pose handler
humanPoseHandler.GetHumanPose(ref humanPose);
// set a specific musle; 9: Neck Nod Down-Up
humanPose.muscles[9] = -20f;
Debug.Log(humanPose.muscles[9]);
// use pose information to actually set the pose;
humanPoseHandler.SetHumanPose(ref humanPose);
Dos adiciones a la respuesta muscular
1, para resolver el problema:
El personaje al que se aplicó se ha movido demasiado lejos de donde debería haber estado cuando humanPoseHandler.SetHumanPose(ref humanPose);
Estaba listo.
Necesitas agregar:
humanPose.bodyPosition = transform.position;
humanPose.bodyRotation = transform.rotation;
Esto mantendrá a tu personaje exactamente donde está ubicado.
2, en realidad, la solución muscular sigue siendo válida cuando se adjunta un AnimatorController al personaje humanoide actual. Solo necesitas cambiar modo de actualizacion por física animada y pon tu codigo de musculo Update()
. Esto hará que su código muscular (que se ejecuta en Update()
) se ejecuta después de los efectos AnimationController (que se ejecutan en FixedUpdate()
que se llama antes Update()
).
Este enfoque te permitirá controlar directamente algunos músculos y usar el efecto Unity IK al mismo tiempo.
nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias
eso es todo,hasta la proxima