引言
在我的上一篇文章中,通过给门添加旋转动作并利用unity中的父子物体关系来更改旋转的轴,巧妙地完成了开关门的动画制作。
但有一个致命的缺陷就是在unity中该程序无法拖动给多个门,若多个门上都使用的给程序,那么当其中一个门触发开门或关门动作时,所有带有该程序的门都将开门或关门。
为解决这个问题,我提供以下这种方式。
在Unity中实现开关门的一种高级方式
核心思路
开关门的触发是由鼠标点击来实现的,我们可以考虑在鼠标点击触发物体时获取当前物体,之后仅控制刚刚获取的物体动作。
实现方式
我们可以在鼠标点击物体时在鼠标位置发射一条射线,射线触碰到的物体即为鼠标点击的物体,获取此物体和它的父级物体,作为接下来操作的对象,这样就只有当前获取的物体会在接下来的程序控制下动作,而其它被该程序文件控制的物体就不会动作。相关代码如下所示:
if (Input.GetMouseButtonDown(0))
{
//Debug.LogFormat("ok{0}",rotatetrigger);
//射线检测
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//得到该物体
clickedObject = hit.collider.gameObject;
//得到它的父级
parentGameObject = clickedObject.transform.parent.gameObject;
}
}
因为使用了父级子级之间的调用,之前在上一篇文章中需要给父级子级分别写一个程序文件的繁琐流程就可以去掉了,直接在门所对应的程序中提供调用它的父级,控制它的父级物体旋转来实现开关门动作。相关代码如下:
//开门
if (rotatetrigger == 1)
{
if (doubledoorcheck==1) //特殊情况,大门双开门
{
bigdoorleft.transform.Rotate(0, -90 * Time.deltaTime, 0);
if (bigdoorleft.transform.rotation.eulerAngles == FirstRotate + new Vector3(0, -90, 0))
{
rotatetrigger = 0;
}
bigdoorright.transform.Rotate(0, 90 * Time.deltaTime, 0);
if (bigdoorright.transform.rotation.eulerAngles == FinalRotate)
{
rotatetrigger = 0;
}
}
else
{
parentGameObject.transform.Rotate(0, 90 * Time.deltaTime, 0);
if (parentGameObject.transform.rotation.eulerAngles == FinalRotate)
{
rotatetrigger = 0;
}
}
}
//关门
if (rotatetrigger >= 2)
{
if (doubledoorcheck==1)
{
bigdoorleft.transform.Rotate(0, 90 * Time.deltaTime, 0);
if (bigdoorleft.transform.rotation.eulerAngles == FirstRotate)
{
rotatetrigger = 0;
}
bigdoorright.transform.Rotate(0, -90 * Time.deltaTime, 0);
if (bigdoorright.transform.rotation.eulerAngles == FirstRotate)
{
rotatetrigger = 0;
}
}
else
{
parentGameObject.transform.Rotate(0, -90 * Time.deltaTime, 0);
if (parentGameObject.transform.rotation.eulerAngles == FirstRotate)
{
rotatetrigger = 0;
}
}
}
该代码里还增添了一种双开门的情况,即控制左侧的门向左开,右侧的门向右开。
程序文件待会儿发布。