Unity 旋转跟随

Unity 使用任意一个局部轴指向目标

效果:

主要用于在编辑器中可视化对象的朝向,同时提供了选择不同轴向的功能。在运行时,物体将根据所选择的轴向朝向目标,并在 Scene 视图中绘制一个带箭头的圆环。

定义轴向枚举:

javascript 复制代码
public enum OnlyAxis
{
    x_Axis,
    y_Axis,
    z_Axis
}
  • 这是一个用于表示轴向的枚举,包括 x 轴、y 轴和 z 轴。

定义变量:

javascript 复制代码
public Transform target; // 要指向的目标物体
[Header("追踪轴向")]
public OnlyAxis Axis = OnlyAxis.x_Axis; // 选择旋转的轴向
private OnlyAxis CurrentAxis = OnlyAxis.x_Axis; // 当前轴向
  • target: 用于指定需要朝向的目标物体。
  • Axis: 用于在 Inspector 窗口中选择旋转的轴向。
  • CurrentAxis: 用于在运行时跟踪当前的轴向。

主要计算:

javascript 复制代码
private void Update()
{
    SetAxis(Axis);

    // 获取目标方向
    Vector3 targetDirection = target.position - transform.position;
    Vector3 RotateAxis = transform.up;

    // 根据选择的轴向,获取目标方向在对应轴上的投影
    Vector3 axisDirection = Vector3.zero;
    switch (CurrentAxis)
    {
        case OnlyAxis.x_Axis:
            axisDirection = Vector3.ProjectOnPlane(targetDirection, transform.right);
            break;
        case OnlyAxis.y_Axis:
            axisDirection = Vector3.ProjectOnPlane(targetDirection, transform.up);
            break;
        case OnlyAxis.z_Axis:
            axisDirection = transform.forward;
            Vector3 dirTemp = transform.forward.normalized;
            RotateAxis = Vector3.ProjectOnPlane(targetDirection, dirTemp);
            break;
    }

    // 计算旋转角度
    Quaternion newRotation = Quaternion.LookRotation(axisDirection, RotateAxis);
    transform.rotation = newRotation;
}
  • SetAxis 方法用于在运行时更新 CurrentAxis,确保在不同的轴向之间正确切换。
  • 在 Update 方法中,获取目标方向,并根据当前选择的轴向计算相应的旋转。最后,将物体的旋转设为新的旋转。

OnDrawGizmosSelected 方法(仅在编辑器中生效):

javascript 复制代码
#if UNITY_EDITOR
    private void OnDrawGizmosSelected()
    {
        DrawCircle();
    }
    public bool is3DDraw = false;
    public float radius = 0.1f;
    public float arrowLength = 0.01f;
    int segments = 20;

    private void DrawCircle()
    {
        float Radius = is3DDraw ? radius : radius * Vector3.Distance(transform.position, SceneView.lastActiveSceneView.camera.transform.position);
        float ArrowLength = is3DDraw ? arrowLength : arrowLength * Vector3.Distance(transform.position, SceneView.lastActiveSceneView.camera.transform.position);

        Gizmos.color = Color.green;
        Vector3 center = transform.position;
        Quaternion rotation = transform.rotation;
        float angleIncrement = 360f / segments;
        for (int i = 0; i < segments; i++)
        {
            float angle = i * angleIncrement;
            Vector3 point = Vector3.zero;
            float nextAngle = (i + 1) * angleIncrement;
            Vector3 nextPoint = Vector3.zero;

            // 根据所选轴向,调整旋转
            switch (Axis)
            {
                case OnlyAxis.x_Axis:
                    point = center + rotation * Quaternion.Euler(angle, 0, 0) * (Vector3.up * Radius);
                    nextPoint = center + rotation * Quaternion.Euler(nextAngle, 0, 0) * (Vector3.up * Radius);
                    if (i == 0)
                    {
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(angle + angleIncrement / 2, 0, 0) * (Vector3.up * (Radius + ArrowLength)));
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(angle + angleIncrement / 2, 0, 0) * (Vector3.up * (Radius - ArrowLength)));
                    }
                    break;
                case OnlyAxis.y_Axis:
                    point = center + rotation * Quaternion.Euler(0, angle, 0) * (Vector3.right * Radius);
                    nextPoint = center + rotation * Quaternion.Euler(0, nextAngle, 0) * (Vector3.right * Radius);
                    if (i == 0)
                    {
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(0, angle + angleIncrement / 2, 0) * (Vector3.right * (Radius + ArrowLength)));
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(0, angle + angleIncrement / 2, 0) * (Vector3.right * (Radius + -ArrowLength)));
                    }
                    break;
                case OnlyAxis.z_Axis:
                    point = center + rotation * Quaternion.Euler(0, 0, angle) * (Vector3.right * Radius);
                    nextPoint = center + rotation * Quaternion.Euler(0, 0, nextAngle) * (Vector3.right * Radius);
                    if (i == 0)
                    {
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(0, 0, angle + angleIncrement / 2) * (Vector3.right * (Radius + ArrowLength)));
                        Gizmos.DrawLine(nextPoint, center + rotation * Quaternion.Euler(0, 0, angle + angleIncrement / 2) * (Vector3.right * (Radius + -ArrowLength)));
                    }
                    break;
            }
            if (i != 1) Gizmos.DrawLine(point, nextPoint);
        }
    }
#endif
  • OnDrawGizmosSelected 方法用于在 Scene 视图中绘制圆环。
  • DrawCircle 方法根据选择的轴向,绘制一个圆环并在第一个点上画一个箭头。

点击下载Demo

相关推荐
EQ-雪梨蛋花汤41 分钟前
【Part 3 Unity VR眼镜端播放器开发与优化】第四节|高分辨率VR全景视频播放性能优化
unity·音视频·vr
与火星的孩子对话5 小时前
Unity进阶课程【六】Android、ios、Pad 终端设备打包局域网IP调试、USB调试、性能检测、控制台打印日志等、C#
android·unity·ios·c#·ip
幻世界6 小时前
【Unity智能模型系列】Unity + MediaPipe + Sentis + ArcFace模型:构建高效人脸识别比对系统
unity·游戏引擎
漫游者Nova14 小时前
虚幻引擎Unreal Engine5恐怖游戏设计制作教程,从入门到精通从零开始完整项目开发实战详细讲解中英字幕
ue5·游戏引擎·虚幻·游戏开发完整教程·恐怖游戏开发
死也不注释1 天前
【Unity 编辑器工具开发:GUILayout 与 EditorGUILayout 对比分析】
unity·编辑器·游戏引擎
小赖同学啊1 天前
物联网中的Unity/Unreal引擎集成:数字孪生与可视化控制
物联网·unity·游戏引擎
Zlzxzw1 天前
使用unity创建项目,进行动画制作
unity·游戏引擎
X_StarX2 天前
【Unity笔记01】基于单例模式的简单UI框架
笔记·ui·unity·单例模式·游戏引擎·游戏开发·大学生
九班长2 天前
Golang服务端处理Unity 3D游戏地图与碰撞的详细实现
3d·unity·golang
ysn111112 天前
NGUI实现反向定位到层级面板结点
unity