1. 程式人生 > >關於“官方案例精選”一書中Mecanim章節中的IK小結部分的無法再5.x以上版本正確觸發

關於“官方案例精選”一書中Mecanim章節中的IK小結部分的無法再5.x以上版本正確觸發

  • 概述:

筆者在“官方案例精選”一書中,第六章的Mecanim中的IK講解的部分,遇到部分疑惑的地方;接下來,為可能有與我相同問題的夥伴,說明下我測試的結果。

  • 提出問題:
  1. 匹配Effector位置的指令碼,放置在Update函式中無法正確的找到位置的問題(書中是指明還在Update函式,但是其實demo裡面的IK指令碼,並沒有把匹配位置的函式,放置在Update中);而是放置在回撥函式OnAnimatorIK(int layerIndex)中
  • 解決辦法:

不要按照書中所描述的,放置指令碼在Update中;而是將這部分程式碼,放置在回撥函式OnAnimatorIK(int layerIndex)中

  • 測試過程:
  1. 首先將官方的demo指令碼,放置在Update中,也是無法正確觸發的情況;
  2. 放置在回撥函式OnAnimatorIK(int layerIndex)中,正確操作
程式碼部分:
  1. 錯誤方式:
 /// <summary>
/// 
/// </summary>

using UnityEngine;
using System;
using System.Collections;
  
[RequireComponent(typeof(Animator))]  

//Name of class must be name of file as well

public class IK : MonoBehaviour {
	
	protected Animator avatar;
	
	public bool ikActive = false;
	public Transform bodyObj = null;
	public Transform leftFootObj = null;
	public Transform rightFootObj = null;
	public Transform leftHandObj = null;
	public Transform rightHandObj = null;
	public Transform lookAtObj = null;
	
	public float leftFootWeightPosition = 1;
	public float leftFootWeightRotation = 1;

	public float rightFootWeightPosition = 1;
	public float rightFootWeightRotation = 1;
	
	public float leftHandWeightPosition = 1;
	public float leftHandWeightRotation = 1;
	
	public float rightHandWeightPosition = 1;
	public float rightHandWeightRotation = 1;

	public float lookAtWeight = 1.0f;
	
	// Use this for initialization
	void Start () 
	{
		avatar = GetComponent<Animator>();
	}

	void OnGUI()
	{

		GUILayout.Label("Activate IK and move the Effectors around in Scene View");
		ikActive = GUILayout.Toggle(ikActive, "Activate IK");
	}

    void Update()
    {
        //不應該把下部分程式碼,放置在Update中
        if (!ikActive)
        {
            avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 0);

            avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot, 0);

            avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);

            avatar.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);

            avatar.SetLookAtWeight(0.0f);

            if (bodyObj != null)
            {
                bodyObj.position = avatar.bodyPosition;
                bodyObj.rotation = avatar.bodyRotation;
            }

            if (leftFootObj != null)
            {
                leftFootObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftFoot);
                leftFootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftFoot);
            }

            if (rightFootObj != null)
            {
                rightFootObj.position = avatar.GetIKPosition(AvatarIKGoal.RightFoot);
                rightFootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightFoot);
            }

            if (leftHandObj != null)
            {
                leftHandObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftHand);
                leftHandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftHand);
            }

            if (rightHandObj != null)
            {
                rightHandObj.position = avatar.GetIKPosition(AvatarIKGoal.RightHand);
                rightHandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightHand);
            }


            if (lookAtObj != null)
            {
                lookAtObj.position = avatar.bodyPosition + avatar.bodyRotation * new Vector3(0, 0.5f, 1);
            }
        }
    }
		
    
	void OnAnimatorIK(int layerIndex)
	{		
		if(avatar)
		{
			if(ikActive)
			{
				avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot,leftFootWeightPosition);
				avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot,leftFootWeightRotation);
							
				avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot,rightFootWeightPosition);
				avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot,rightFootWeightRotation);
	
				avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand,leftHandWeightPosition);
				avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand,leftHandWeightRotation);
							
				avatar.SetIKPositionWeight(AvatarIKGoal.RightHand,rightHandWeightPosition);
				avatar.SetIKRotationWeight(AvatarIKGoal.RightHand,rightHandWeightRotation);
				
				avatar.SetLookAtWeight(lookAtWeight,0.3f,0.6f,1.0f,0.5f);
				
				if(bodyObj != null)
				{
					avatar.bodyPosition = bodyObj.position;
					avatar.bodyRotation = bodyObj.rotation;
				}				

				if(leftFootObj != null)
				{
					avatar.SetIKPosition(AvatarIKGoal.LeftFoot,leftFootObj.position);
					avatar.SetIKRotation(AvatarIKGoal.LeftFoot,leftFootObj.rotation);
				}				
			
				if(rightFootObj != null)
				{
					avatar.SetIKPosition(AvatarIKGoal.RightFoot,rightFootObj.position);
					avatar.SetIKRotation(AvatarIKGoal.RightFoot,rightFootObj.rotation);
				}				

				if(leftHandObj != null)
				{
					avatar.SetIKPosition(AvatarIKGoal.LeftHand,leftHandObj.position);
					avatar.SetIKRotation(AvatarIKGoal.LeftHand,leftHandObj.rotation);
				}				
			
				if(rightHandObj != null)
				{
					avatar.SetIKPosition(AvatarIKGoal.RightHand,rightHandObj.position);
					avatar.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
				}				
				
				if(lookAtObj != null)
				{
					avatar.SetLookAtPosition(lookAtObj.position);
				}				
			}
			else
			{
				
			}
		}
	}  
}

2. 正確方式:

using UnityEngine;

public class ConfigIK : MonoBehaviour
{

    public Transform bodyObj;
    public Transform headObj;
    public Transform lefthandObj;
    public Transform righthandObj;
    public Transform leftfootObj;
    public Transform rightfootObj;

    private Animator avatar;
    private bool isActive = false;


    void Start()
    {
        avatar = GetComponent<Animator>();



    }


    void Update()
    {


    }

    void OnAnimatorIK(int layerIndex)
    {
        if (isActive)
        {
            avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1);
            avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);
            avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand, 1);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand, 1);
            avatar.SetIKPositionWeight(AvatarIKGoal.RightHand, 1);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightHand, 1);
            avatar.SetLookAtWeight(1.0f, 0.8f);

            if (leftfootObj != null)
            {
                avatar.SetIKPosition(AvatarIKGoal.LeftFoot, leftfootObj.position);
                avatar.SetIKRotation(AvatarIKGoal.LeftFoot, leftfootObj.rotation);
            }
            if (rightfootObj != null)
            {
                avatar.SetIKPosition(AvatarIKGoal.RightFoot, rightfootObj.position);
                avatar.SetIKRotation(AvatarIKGoal.RightFoot, rightfootObj.rotation);
            }
            if (lefthandObj != null)
            {
                avatar.SetIKPosition(AvatarIKGoal.LeftHand, lefthandObj.position);
                avatar.SetIKRotation(AvatarIKGoal.LeftHand, lefthandObj.rotation);
            }
            if (righthandObj != null)
            {
                avatar.SetIKPosition(AvatarIKGoal.RightHand, righthandObj.position);
                avatar.SetIKRotation(AvatarIKGoal.RightHand, righthandObj.rotation);
            }
            if (headObj != null)
            {
                avatar.SetLookAtPosition(headObj.position);
            }
            if (bodyObj != null)
            {
                avatar.bodyPosition = bodyObj.position;
                avatar.bodyRotation = bodyObj.rotation;
            }
        }
        else
        {

            avatar.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 0);
            avatar.SetIKPositionWeight(AvatarIKGoal.RightFoot, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightFoot, 0);
            avatar.SetIKPositionWeight(AvatarIKGoal.LeftHand, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.LeftHand, 0);
            avatar.SetIKPositionWeight(AvatarIKGoal.RightHand, 0);
            avatar.SetIKRotationWeight(AvatarIKGoal.RightHand, 0);
            avatar.SetLookAtWeight(0f);

            if (bodyObj != null)
            {
                bodyObj.position = avatar.bodyPosition;
                bodyObj.rotation = avatar.bodyRotation;
            }
            if (lefthandObj != null)
            {
                lefthandObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftHand);
                lefthandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftHand);
            }
            if (righthandObj != null)
            {
                righthandObj.position = avatar.GetIKPosition(AvatarIKGoal.RightHand);
                righthandObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightHand);
            }
            if (leftfootObj != null)
            {
                leftfootObj.position = avatar.GetIKPosition(AvatarIKGoal.LeftFoot);
                leftfootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.LeftFoot);
            }
            if (rightfootObj != null)
            {
                rightfootObj.position = avatar.GetIKPosition(AvatarIKGoal.RightFoot);
                rightfootObj.rotation = avatar.GetIKRotation(AvatarIKGoal.RightFoot);
            }
            if (headObj != null)
                headObj.position = avatar.bodyPosition + avatar.bodyRotation * new Vector3(0, 0.5f, 1.0f);

        }
    }

    void OnGUI()
    {
        isActive = GUILayout.Toggle(isActive, "isActive");
    }
}
  • 總結:

筆者使用的Unity是5.3.6版本·

(我記得在最初學這個的時候,並沒有想到此問題,估計是unity版本高了的問題存在)