【问题标题】:Unity 3D - Move Humanoid head muscles using scriptUnity 3D - 使用脚本移动人形头部肌肉
【发布时间】:2018-02-12 06:13:48
【问题描述】:

目标

我想使用脚本在给定 x、y、z 旋转值的情况下旋转人形角色的头部(不使用场景中的任何其他对象作为“看”方向)。

我想做什么

设置人形角色的绑定时(humanoid prefab --> Rig --> Animation Type: Humanoid --> Configure --> Muscles & Settings),您会看到以下界面:https://docs.unity3d.com/Manual/MuscleDefinitions.html

在此菜单中,在 Head 下,您可以拖动滑块进行移动,例如你的人形头部上下。我想用一个脚本来达到同样的效果,但我不知道该怎么做。

资源

这个问题从未通过示例代码得到正确答案:https://answers.unity.com/questions/824628/can-we-using-script-to-moving-the-muscles-in-unity.html

我想我必须对HumanPose.muscles (https://docs.unity3d.com/ScriptReference/HumanPose-muscles.html) 做点什么,但是由于缺少代码示例,我不知道如何解决这个问题。

编辑 3:此链接包含 HumanPose 的代码示例,但我还没有让它工作:https://forum.unity.com/threads/humanposehandler.430354/

问题

如何获取人形角色的头部肌肉并通过脚本赋予值来旋转它们? (或任何其他方式如何使用头部旋转值旋转头部,而场景中没有另一个对象)。任何帮助将不胜感激。

编辑 1 & 2:示例代码

我收到一条 JSON 格式的消息,我从中提取弧度值并将其更改为度数:

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

我不太清楚如何设置头骨或肌肉。大多数示例仅提供代码的 sn-p,因此我正在努力弄清楚它是如何工作的。

编辑 2:我觉得我快接近了,但 anim.SetBoneLocalRotation(HumanBodyBones.Head, rotation); 似乎被忽略了。

编辑 4:我在 Github 上放了一个简单版本的头部旋转尝试:https://github.com/NumesSanguis/Basic-Unity-Head-Rotation

【问题讨论】:

  • 为什么不从脚本中旋转与头部相关的骨骼?
  • 你能告诉我你是怎么做到的吗?我添加了一个代码 sn-p,其中包含我如何获取旋转值,但不知道如何将其应用于头骨。
  • 人形机器人会被动画化吗?

标签: unity3d


【解决方案1】:

经过一段时间的测试,我想通了。

  1. 首先,将animator设置为IK Pass。

  1. 然后在OnAnimatorIK 方法中使用SetBoneLocalRotation。您可以在此处了解有关此方法的更多信息: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));
	}
}

【讨论】:

  • 感谢您的努力,它正在工作!我接受了您的回答,因为您是第一个,并且您的方法可以附加 AnimateController。请参阅我对肌肉价值方法的回答,并使用您和我朋友的解决方案链接到完整的 Unity 项目。
【解决方案2】:

感谢@ZayedUpal 头部骨骼旋转工作正常,感谢一位朋友,设置肌肉值也工作正常!

这两个选项的完整 Unity 3D 项目可以在这里找到:https://github.com/NumesSanguis/Basic-Unity-Head-Rotation

肌肉值的代码sn-p方法:

//   !!! 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);
}

【讨论】:

  • 我在使用这个脚本时遇到了问题。当 humanPoseHandler.SetHumanPose(ref humanPose);已设置。 Bone 示例运行良好......
【解决方案3】:

两个除了肌肉答案

1、解决问题:

在设置humanPoseHandler.SetHumanPose(ref humanPose); 时,应用它的角色与他应该在的位置相距甚远。

你需要添加:

humanPose.bodyPosition = transform.position;
humanPose.bodyRotation = transform.rotation;

这将使你的角色保持在它所在的位置。

2,实际上,当AnimatorController附加到当前人形角色时,肌肉解决方案仍然有效。您只需将 Update Mode 切换到 Animate Physics 并将您的肌肉代码放入 Update()。这将使你的肌肉代码(在 Update() 中执行)在 AnimationController 效果(在 FixedUpdate() 中执行,比 Update() 更早调用)之后执行。

这种方法可以让你直接控制一些肌肉,同时使用 Unity IK 效果。

【讨论】:

    猜你喜欢
    • 2020-12-14
    • 2019-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 2018-01-16
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    相关资源
    最近更新 更多