3D物体在UGUI下的坐标映射
这个标题着实不好取。举例,譬如怪物的血条总是跟随者怪物移动而移动,因而我们需要实时的更新这个血条的坐标。类似的,还有很多应用场景。归结起来就如标题所示–“3D物体在UGUI下的坐标映射”。其实并不 难,只是实际工作中发现经常用到,故总结为一个工具函数,方便以后工作使用。
下面看我在 UGUI的Canvas下是如何实现的。
关于坐标转换,肯定离不开相机,我们先来考虑相机。毫无疑问,我们将3D场景物体的坐标转换为UI 层级下的坐标,肯定需要两个相机,一个是SceneCamera,一个是UICamera。这里值得注意的是UICamera需要设置成正交相机.当然,你的UI相机也可以是透视相机,但是在做坐标转换的时候就会复杂一些,有需要的时候再考虑,暂时考虑通用性比较高的。当然,SceneCamera就必须是透视相机了。
归纳
以下是具体代码,主要是思路还是把3D物体的世界坐标转换为视口坐标,然后在UI相机之下,把该视口坐标转换为Canvas下的世界坐标,赋给UI对象,并校正Z轴。提供UI对象位置偏移的重载。
using UnityEngine;
using System.Collections;
public class Utility {
/// <summary>
/// Correct the position of the ui object to the specified 3D position in scene.
/// </summary>
public static void ScenePositionToUIPosition( Camera sceneCamera,
Camera uiCamera,
Vector3 posInScene,
Transform uiTarget){
Vector3 viewportPos = sceneCamera.WorldToViewportPoint( posInScene );//unify the position to viewport point.
Vector3 worldPos = uiCamera.ViewportToWorldPoint( viewportPos );
uiTarget.position = worldPos;//set world position.
Vector3 localPos = uiTarget.localPosition;
localPos.z = 0f;//ignore z axis offset.
uiTarget.localPosition = localPos;//correct the local position of the ui target.
}
/// <summary>
/// Correct the position of the ui object to the specified 3D position in scene.
/// </summary>
public static void ScenePositionToUIPosition( Camera sceneCamera,
Camera uiCamera,
Vector3 posInScene,
Transform uiTarget,
Vector2 offset){
ScenePositionToUIPosition( sceneCamera, uiCamera, posInScene, uiTarget );
uiTarget.localPosition += (Vector3)offset;
}
}
例子
我们希望UI 随着球体运动而运动,且在球体上方偏移一定长度。
using UnityEngine;
using System.Collections;
public class Test : MonoBehaviour {
public Camera UICamera;
public Camera SceneCamera;
public Transform TargetSceneObj;
public Transform TargetUIObj;
// Update is called once per frame
void Update () {
Utility.ScenePositionToUIPosition( SceneCamera,
UICamera,
TargetSceneObj.position,
TargetUIObj,
new Vector2(0, 30f) );
}
}
实际运行效果