当前位置: 首页 > news >正文

潜江网站建设重要新闻今天8条新闻

潜江网站建设,重要新闻今天8条新闻,广告设计公司绩效考核,做网站网站建设教程文章目录功能简介实现步骤获取看向的位置获取头部的位置修改头部的朝向限制旋转角度超出限制范围时自动回正如何让指定动画不受影响功能简介 如图所示,当相机的视角转动时,Avatar角色的头部会同步转动,看向视角的方向。 实现步骤 获取看向的…

文章目录

  • 功能简介
  • 实现步骤
    • 获取看向的位置
    • 获取头部的位置
    • 修改头部的朝向
    • 限制旋转角度
    • 超出限制范围时自动回正
  • 如何让指定动画不受影响


功能简介

如图所示,当相机的视角转动时,Avatar角色的头部会同步转动,看向视角的方向。

功能示例

实现步骤

获取看向的位置

Avatar看向的位置即相机前方一定距离的某个坐标,该距离偏大于相机与Avatar角色的距离即可,可以取100来代表:

//获取看向的位置
private Vector3 GetLookAtPosition()
{//主相机前方100个单位的位置return mainCamera.transform.position + mainCamera.transform.forward * 100f;
}

获取头部的位置

头部位置可以通过Animator组件中的GetBoneTransform接口来获取

GetBoneTransform

示例如下:

using UnityEngine;namespace SK.Framework.Avatar
{public class HeadTrack : MonoBehaviour{//动画组件[SerializeField] private Animator animator; private Camera mainCamera; //主相机private Transform head; //头部private void Start(){mainCamera = Camera.main ?? FindObjectOfType<Camera>();head = animator.GetBoneTransform(HumanBodyBones.Head);}//获取看向的位置private Vector3 GetLookAtPosition(){//主相机前方100个单位的位置return mainCamera.transform.position + mainCamera.transform.forward * 100f;}}
}

有了头部的位置后,就可以计算头部的高度,声明一个变量headHeight来记录头部高度:

headHeight = Vector3.Distance(transform.position, head.position);

修改头部的朝向

有了看向的坐标和头部的坐标,就取得了看向的朝向,在LateUpdate中赋值该头部朝向,注意一定要使用LateUpdate,因为Animator动画组件在控制Avatar各骨骼的朝向,使用LateUpdate可以确保我们的旋转值修改起作用。

using UnityEngine;namespace SK.Framework.Avatar
{public class HeadTrack : MonoBehaviour{//动画组件[SerializeField] private Animator animator; private Camera mainCamera; //主相机private Transform head; //头部private float headHeight; //头部的高度private void Start(){mainCamera = Camera.main ?? FindObjectOfType<Camera>();head = animator.GetBoneTransform(HumanBodyBones.Head);headHeight = Vector3.Distance(transform.position, head.position);}/// <summary>/// 看向某点/// </summary>/// <param name="position"></param>public void LookAtPosition(Vector3 position){//头部位置Vector3 headPosition = transform.position + transform.up * headHeight;//朝向Quaternion lookRotation = Quaternion.LookRotation(position - headPosition);head.rotation = lookRotation;}private void LateUpdate(){Debug.DrawLine(transform.position + transform.up * headHeight, GetLookAtPosition());LookAtPosition(GetLookAtPosition());}//获取看向的位置private Vector3 GetLookAtPosition(){//主相机前方100个单位的位置return mainCamera.transform.position + mainCamera.transform.forward * 100f;}}
}

如图所示,我们已经实现了头部的转向,但是旋转值过大会导致反人类现象,因此需要将旋转值进行限制。

限制旋转角度

//水平方向上的角度限制
[SerializeField] private Vector2 horizontalAngleLimit = new Vector2(-100f, 100f); //垂直方向上的角度限制
[SerializeField] private Vector2 verticalAngleLimit = new Vector2(-60f, 60f); 

封装一个角度标准化的函数,当角度大于180度时减360度,当角度小于180度时加360度:

//角度标准化
private float NormalizeAngle(float angle)
{if (angle > 180) angle -= 360f;else if (angle < -180) angle += 360f;return angle;
}

封装看向某点的函数:

/// <summary>
/// 看向某点
/// </summary>
/// <param name="position"></param>
public void LookAtPosition(Vector3 position)
{//头部位置Vector3 headPosition = transform.position + transform.up * headHeight;//朝向Quaternion lookRotation = Quaternion.LookRotation(position - headPosition);Vector3 eulerAngles = lookRotation.eulerAngles - transform.rotation.eulerAngles;float x = NormalizeAngle(eulerAngles.x);float y = NormalizeAngle(eulerAngles.y);x = Mathf.Clamp(x, verticalAngleLimit.x, verticalAngleLimit.y);y = Mathf.Clamp(y, horizontalAngleLimit.x, horizontalAngleLimit.y);Quaternion rotY = Quaternion.AngleAxis(y, head.InverseTransformDirection(transform.up));head.rotation *= rotY;Quaternion rotX = Quaternion.AngleAxis(x, head.InverseTransformDirection(transform.TransformDirection(Vector3.right)));head.rotation *= rotX;
}

超出限制范围时自动回正

当角度超出限制的范围时,将头部自动回正,可以在GetLookAtPosition函数中加入判断,声明autoTurnback变量标识是否自动回正:

//获取看向的位置
private Vector3 GetLookAtPosition()
{Vector3 position = mainCamera.transform.position + mainCamera.transform.forward * 100f;if (!autoTurnback) return position;Vector3 direction = position - (transform.position + transform.up * headHeight);Quaternion lookRotation = Quaternion.LookRotation(direction, transform.up);Vector3 angle = lookRotation.eulerAngles - transform.eulerAngles;float x = NormalizeAngle(angle.x);float y = NormalizeAngle(angle.y);bool isInRange = x >= verticalAngleLimit.x && x <= verticalAngleLimit.y&& y >= horizontalAngleLimit.x && y <= horizontalAngleLimit.y;return isInRange ? position : (transform.position + transform.up * headHeight + transform.forward);
}

加入插值运算,使自动回正时有过渡过程,代码如下:

using UnityEngine;namespace SK.Framework.Avatar
{public class HeadTrack : MonoBehaviour{[Tooltip("动画组件"), SerializeField] private Animator animator; [Tooltip("水平方向上的角度限制"), SerializeField] private Vector2 horizontalAngleLimit = new Vector2(-70f, 70f); [Tooltip("垂直方向上的角度限制"), SerializeField] private Vector2 verticalAngleLimit = new Vector2(-60f, 60f);[Tooltip("超出限制范围时自动回正"), SerializeField] private bool autoTurnback = true;[Tooltip("插值速度"), SerializeField] private float lerpSpeed = 5f;private Camera mainCamera; //主相机private Transform head; //头部private float headHeight; //头部的高度private float angleX;private float angleY;private void Start(){mainCamera = Camera.main ?? FindObjectOfType<Camera>();head = animator.GetBoneTransform(HumanBodyBones.Head);headHeight = Vector3.Distance(transform.position, head.position);}/// <summary>/// 看向某点/// </summary>/// <param name="position"></param>public void LookAtPosition(Vector3 position){//头部位置Vector3 headPosition = transform.position + transform.up * headHeight;//朝向Quaternion lookRotation = Quaternion.LookRotation(position - headPosition);Vector3 eulerAngles = lookRotation.eulerAngles - transform.rotation.eulerAngles;float x = NormalizeAngle(eulerAngles.x);float y = NormalizeAngle(eulerAngles.y);angleX = Mathf.Clamp(Mathf.Lerp(angleX, x, Time.deltaTime * lerpSpeed), verticalAngleLimit.x, verticalAngleLimit.y);angleY = Mathf.Clamp(Mathf.Lerp(angleY, y, Time.deltaTime * lerpSpeed), horizontalAngleLimit.x, horizontalAngleLimit.y);Quaternion rotY = Quaternion.AngleAxis(angleY, head.InverseTransformDirection(transform.up));head.rotation *= rotY;Quaternion rotX = Quaternion.AngleAxis(angleX, head.InverseTransformDirection(transform.TransformDirection(Vector3.right)));head.rotation *= rotX;}//角度标准化private float NormalizeAngle(float angle){if (angle > 180) angle -= 360f;else if (angle < -180) angle += 360f;return angle;}private void LateUpdate(){LookAtPosition(GetLookAtPosition());}//获取看向的位置private Vector3 GetLookAtPosition(){Vector3 position = mainCamera.transform.position + mainCamera.transform.forward * 100f;if (!autoTurnback) return position;Vector3 direction = position - (transform.position + transform.up * headHeight);Quaternion lookRotation = Quaternion.LookRotation(direction, transform.up);Vector3 angle = lookRotation.eulerAngles - transform.eulerAngles;float x = NormalizeAngle(angle.x);float y = NormalizeAngle(angle.y);bool isInRange = x >= verticalAngleLimit.x && x <= verticalAngleLimit.y && y >= horizontalAngleLimit.x && y <= horizontalAngleLimit.y;return isInRange ? position : (transform.position + transform.up * headHeight + transform.forward); }}
}

自动回正

如何让指定动画不受影响

如果我们想要在播放某个动画时不让头部转动,可以通过Tag标签来解决,如下图所示,为Hi动画增加IgnoreHeadTrack标签:

Tag
在代码中加入判断:

//获取看向的位置
private Vector3 GetLookAtPosition()
{AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);if (animatorStateInfo.IsTag("IgnoreHeadTrack"))return transform.position + transform.up * headHeight + transform.forward;Vector3 position = mainCamera.transform.position + mainCamera.transform.forward * 100f;if (!autoTurnback) return position;Vector3 direction = position - (transform.position + transform.up * headHeight);Quaternion lookRotation = Quaternion.LookRotation(direction, transform.up);Vector3 angle = lookRotation.eulerAngles - transform.eulerAngles;float x = NormalizeAngle(angle.x);float y = NormalizeAngle(angle.y);bool isInRange = x >= verticalAngleLimit.x && x <= verticalAngleLimit.y&& y >= horizontalAngleLimit.x && y <= horizontalAngleLimit.y;return isInRange ? position : (transform.position + transform.up * headHeight + transform.forward);
}

完整代码:

using UnityEngine;namespace SK.Framework.Avatar
{public class HeadTrack : MonoBehaviour{[Tooltip("动画组件"), SerializeField] private Animator animator; [Tooltip("水平方向上的角度限制"), SerializeField] private Vector2 horizontalAngleLimit = new Vector2(-70f, 70f); [Tooltip("垂直方向上的角度限制"), SerializeField] private Vector2 verticalAngleLimit = new Vector2(-60f, 60f);[Tooltip("超出限制范围时自动回正"), SerializeField] private bool autoTurnback = true;[Tooltip("插值速度"), SerializeField] private float lerpSpeed = 5f;private Camera mainCamera; //主相机private Transform head; //头部private float headHeight; //头部的高度private float angleX;private float angleY;private void Start(){mainCamera = Camera.main ?? FindObjectOfType<Camera>();head = animator.GetBoneTransform(HumanBodyBones.Head);headHeight = Vector3.Distance(transform.position, head.position);}/// <summary>/// 看向某点/// </summary>/// <param name="position"></param>public void LookAtPosition(Vector3 position){//头部位置Vector3 headPosition = transform.position + transform.up * headHeight;//朝向Quaternion lookRotation = Quaternion.LookRotation(position - headPosition);Vector3 eulerAngles = lookRotation.eulerAngles - transform.rotation.eulerAngles;float x = NormalizeAngle(eulerAngles.x);float y = NormalizeAngle(eulerAngles.y);angleX = Mathf.Clamp(Mathf.Lerp(angleX, x, Time.deltaTime * lerpSpeed), verticalAngleLimit.x, verticalAngleLimit.y);angleY = Mathf.Clamp(Mathf.Lerp(angleY, y, Time.deltaTime * lerpSpeed), horizontalAngleLimit.x, horizontalAngleLimit.y);Quaternion rotY = Quaternion.AngleAxis(angleY, head.InverseTransformDirection(transform.up));head.rotation *= rotY;Quaternion rotX = Quaternion.AngleAxis(angleX, head.InverseTransformDirection(transform.TransformDirection(Vector3.right)));head.rotation *= rotX;}//角度标准化private float NormalizeAngle(float angle){if (angle > 180) angle -= 360f;else if (angle < -180) angle += 360f;return angle;}private void LateUpdate(){LookAtPosition(GetLookAtPosition());}//获取看向的位置private Vector3 GetLookAtPosition(){AnimatorStateInfo animatorStateInfo = animator.GetCurrentAnimatorStateInfo(0);if (animatorStateInfo.IsTag("IgnoreHeadTrack"))return transform.position + transform.up * headHeight + transform.forward;Vector3 position = mainCamera.transform.position + mainCamera.transform.forward * 100f;if (!autoTurnback) return position;Vector3 direction = position - (transform.position + transform.up * headHeight);Quaternion lookRotation = Quaternion.LookRotation(direction, transform.up);Vector3 angle = lookRotation.eulerAngles - transform.eulerAngles;float x = NormalizeAngle(angle.x);float y = NormalizeAngle(angle.y);bool isInRange = x >= verticalAngleLimit.x && x <= verticalAngleLimit.y && y >= horizontalAngleLimit.x && y <= horizontalAngleLimit.y;return isInRange ? position : (transform.position + transform.up * headHeight + transform.forward); }}
}

文章转载自:
http://mediad.c7495.cn
http://crummie.c7495.cn
http://muscleman.c7495.cn
http://seymour.c7495.cn
http://abomination.c7495.cn
http://inform.c7495.cn
http://swale.c7495.cn
http://countermove.c7495.cn
http://biblist.c7495.cn
http://riata.c7495.cn
http://pesade.c7495.cn
http://seminivorous.c7495.cn
http://yauld.c7495.cn
http://planting.c7495.cn
http://karman.c7495.cn
http://poplin.c7495.cn
http://downwash.c7495.cn
http://hypercriticism.c7495.cn
http://adultness.c7495.cn
http://darkroom.c7495.cn
http://repertory.c7495.cn
http://outachieve.c7495.cn
http://prefab.c7495.cn
http://practolol.c7495.cn
http://buses.c7495.cn
http://wedeln.c7495.cn
http://communicate.c7495.cn
http://filicauline.c7495.cn
http://sudor.c7495.cn
http://fizz.c7495.cn
http://capuche.c7495.cn
http://squib.c7495.cn
http://thump.c7495.cn
http://decrepitate.c7495.cn
http://ephemera.c7495.cn
http://morass.c7495.cn
http://graze.c7495.cn
http://tatou.c7495.cn
http://shovelboard.c7495.cn
http://autarchist.c7495.cn
http://hippopotamus.c7495.cn
http://ophiolater.c7495.cn
http://skinhead.c7495.cn
http://ignescent.c7495.cn
http://superduper.c7495.cn
http://surmount.c7495.cn
http://riverward.c7495.cn
http://teutonic.c7495.cn
http://batik.c7495.cn
http://odm.c7495.cn
http://antepaschal.c7495.cn
http://fantastically.c7495.cn
http://forecasting.c7495.cn
http://stemmed.c7495.cn
http://neper.c7495.cn
http://expectantly.c7495.cn
http://grutten.c7495.cn
http://backswept.c7495.cn
http://incapable.c7495.cn
http://hematoid.c7495.cn
http://hillcrest.c7495.cn
http://smoketight.c7495.cn
http://oliphant.c7495.cn
http://dipnoan.c7495.cn
http://stupor.c7495.cn
http://perique.c7495.cn
http://pismire.c7495.cn
http://portage.c7495.cn
http://resplendence.c7495.cn
http://delft.c7495.cn
http://organum.c7495.cn
http://credendum.c7495.cn
http://ability.c7495.cn
http://congeries.c7495.cn
http://photo.c7495.cn
http://diggable.c7495.cn
http://adnoun.c7495.cn
http://indivertible.c7495.cn
http://corfiote.c7495.cn
http://alexander.c7495.cn
http://ranging.c7495.cn
http://nepit.c7495.cn
http://unexceptional.c7495.cn
http://tomnoddy.c7495.cn
http://tumbleweed.c7495.cn
http://feeding.c7495.cn
http://anticlimactic.c7495.cn
http://sigmoidostomy.c7495.cn
http://dehumanize.c7495.cn
http://whoops.c7495.cn
http://sole.c7495.cn
http://whine.c7495.cn
http://uralborite.c7495.cn
http://grimily.c7495.cn
http://sacerdotal.c7495.cn
http://criminality.c7495.cn
http://vanman.c7495.cn
http://budget.c7495.cn
http://hejaz.c7495.cn
http://flockbed.c7495.cn
http://www.zhongyajixie.com/news/69876.html

相关文章:

  • 室内设计网课seo搜索引擎优化求职简历
  • 百度指数做网站优化搜索关键词
  • google关键词排名优化专业北京seo公司
  • 电商平台网站开发怎么快速优化网站排名
  • 网站建设赠送seo云南网络推广
  • 七牛搭建网站百度推广系统营销平台
  • asp.net使用wordpress搜狗网站seo
  • 手机在线做网站关键词工具有哪些
  • 搜网站技巧哈尔滨企业网站seo
  • 做图表网站人民网疫情最新消息
  • 免费一键logo在线设计网站播放视频速度优化
  • 龙岗网站制作市场企业站seo
  • 上海品牌网站开发郑州网站推广
  • 免费全自动网页制作系统谷歌优化排名怎么做
  • 买完服务器怎么做网站网站历史权重查询
  • 企业网站建设公司那家好网址网域ip地址查询
  • 视觉设计的网站专业提升关键词排名工具
  • 无锡网站建设有限公司搜索引擎的工作原理有哪些
  • 给个网站2022年手机上能用的西安疫情最新数据消息中高风险地区
  • 996建站网站制作3d建模培训班一般多少钱
  • 传媒公司靠什么赚钱兰州seo技术优化排名公司
  • 个人网站首页怎么做谷歌优化怎么做
  • 上海网站公司宁波seo基础入门
  • 做IT的会做网站吗快速优化系统
  • 空间怎么做网站百度快速排名优化技术
  • 婴儿做相册的网站北京seo包年
  • 手机网站建设课程教学百度推广产品
  • 网站源码分享平台常州网站建设优化
  • wordpress改变底部logo重庆优化seo
  • 海口市做网站的公司万网域名查询注册商