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

相关推荐
张老师带你学36 分钟前
unity 树资源 有樱花树 buildin
科技·游戏·unity·游戏引擎·模型
魔士于安38 分钟前
unity 植物 不常见 花 触手植物
游戏·unity·游戏引擎·贴图·模型
魔士于安2 小时前
unity=>传送门特效 带自由视角旋转放大 鼠标操作
前端·游戏·unity·游戏引擎·贴图·模型
南無忘码至尊2 小时前
Unity学习90天 - 第4天 - 认识物理系统基础并实现物体碰撞反弹
学习·unity·游戏引擎
南無忘码至尊3 小时前
Unity学习90天 - 第4天 - 学习预制体 Prefab + 实例化并实现按鼠标生成子弹
学习·unity·游戏引擎
魔士于安16 小时前
Unity资源Toon City Pack 发电厂 工地 公园 地铁站口 银行 车 直升飞机 可动 URP
游戏·unity·游戏引擎·贴图·模型
SmartRadio18 小时前
NRF52833 + MPU6050 室内定位跟随无人机
游戏引擎·无人机·cocos2d
心前阳光19 小时前
Unity之运行时标准材质半透明无效果
unity·游戏引擎·材质
张老师带你学21 小时前
Unity buildin 石头围墙 树木 树墩子 卡通风格 栅栏 小桥 低多边形
科技·游戏·unity·游戏引擎·模型
呆呆敲代码的小Y1 天前
【Unity工具篇】| 使用YooAsset接入自己的游戏项目,实现完整热更新流程
游戏·unity·游戏引擎·热更新·yooasset·资源热更新