有个需求要实现子物体跟随父物体效果,但是不能使用父子物体关系来实现,这时候就需要自己计算。如果只是实现简单的跟随移动是比较简单的,但是这里面有个难点是旋转问题,如何做到父物体旋转的同时子物体也跟随旋转呢?实际上子物体的跟随旋转就是子物体的初始朝向轴一直指向父物体,只需要实现物体的某个轴时刻指向父物体,先计算位置再计算朝向就能实现。主要代码如下:
using UnityEngine;
public class 子物体 : MonoBehaviour
{
public Transform 父物体;
Vector3 子物体方向轴;
Vector3 父物体方向轴;
// Start is called before the first frame update
void Start()
{
子物体方向轴 = transform.InverseTransformDirection(父物体.position - transform.position);
父物体方向轴 = 父物体.InverseTransformDirection(transform.position - 父物体.position);
}
// Update is called once per frame
void Update()
{
transform.position = 父物体.position + 父物体.TransformDirection(父物体方向轴);
AxisLookAt(transform, 父物体.position, 子物体方向轴);
}
/// <summary>
/// 用某个轴去朝向物体
/// </summary>
/// <param name="tr_self">朝向的本体</param>
/// <param name="lookPos">朝向的目标</param>
/// <param name="directionAxis">方向轴,取决于你用那个方向去朝向</param>
public static void AxisLookAt(Transform tr_self, Vector3 lookPos, Vector3 directionAxis)
{
Quaternion rotation = tr_self.rotation;
Vector3 targetDir = lookPos - tr_self.position;
//指定哪根轴朝向目标,自行修改Vector3的方向
Vector3 fromDir = tr_self.rotation * directionAxis;
//计算垂直于当前方向和目标方向的轴
Vector3 axis = Vector3.Cross(fromDir, targetDir);
//计算当前方向和目标方向的夹角
float angle = Vector3.Angle(fromDir, targetDir);
//将当前朝向向目标方向旋转一定角度,这个角度值可以做插值
tr_self.rotation = Quaternion.AngleAxis(angle, axis) * rotation;
}
}
把此脚本挂到子物体上面,然后指定公共变量父物体就可以了。
除了以上思路以外还有更简单的方法,直接通过位置与旋转偏移量来计算更加简洁,具体代码如下:
using UnityEngine;
public class 子物体 : MonoBehaviour
{
public Transform 父物体;
Vector3 位置偏移量;
Quaternion 旋转偏移量;
void Start()
{
位置偏移量 = 父物体.InverseTransformDirection(transform.position - 父物体.position);
旋转偏移量 = Quaternion.Inverse(父物体.rotation) * transform.rotation;
}
void Update()
{
transform.rotation = 父物体.rotation * 旋转偏移量;
transform.position = 父物体.position + 父物体.TransformDirection(位置偏移量);
}
}