Unity 使用任意一个局部轴指向目标
效果:
主要用于在编辑器中可视化对象的朝向,同时提供了选择不同轴向的功能。在运行时,物体将根据所选择的轴向朝向目标,并在 Scene 视图中绘制一个带箭头的圆环。
定义轴向枚举:
public enum OnlyAxis
{
x_Axis,
y_Axis,
z_Axis
}
- 这是一个用于表示轴向的枚举,包括 x 轴、y 轴和 z 轴。
定义变量:
public Transform target; // 要指向的目标物体
[Header("追踪轴向")]
public OnlyAxis Axis = OnlyAxis.x_Axis; // 选择旋转的轴向
private OnlyAxis CurrentAxis = OnlyAxis.x_Axis; // 当前轴向
- target: 用于指定需要朝向的目标物体。
- Axis: 用于在 Inspector 窗口中选择旋转的轴向。
- CurrentAxis: 用于在运行时跟踪当前的轴向。
主要计算:
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 方法(仅在编辑器中生效):
#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 方法根据选择的轴向,绘制一个圆环并在第一个点上画一个箭头。