用FairyGUI的时候,美术想做一些3D效果的UI,但是在编辑器上不支持,需要我们Unity这边帮助实现,当时的大体思路和之前做投影效果类似,通过自定义数据这块在Unity这对GObject进行修改。https://blog.csdn.net/wangjiangrong/article/details/95341797
但是FairyGUI的默认摄像机Stage Camera是正交摄像机,实现了GObject的旋转之后并没有3D的效果,需要使用摄像机的透视模式来处理。关于如何保证UI正好完整显示在屏幕上,在上一篇关于摄像机Size的问题上也进行了分析https://blog.csdn.net/wangjiangrong/article/details/96338240
所以,我们需要做的就是,首先修改好Stage Camera,然后美术在Unity通过旋转2DUI达到其预期要的3D效果后,纪录其旋转值,通过FairyGUI那给需要3D效果的UI,在自定义属性处添加旋转值,最后我们在解析的时候对配置了旋转值的物体进行旋转即可。
效果如下:
FairGUI,给左边的按钮配置了UIRotation:0,-30,0|PositionZ:-50(旋转角度以及Z轴),右边的按钮配置了UIRotation:0,30,0
Unity解析后显示如下
可以看见有了3D的效果,虽然丑了点=。=
下面进行设置以及代码的修改:
首先将Stage Camera的Projection改为Perspective,Field of View设置为90。同时对StageCamera.cs脚本进行修改,我们将摄像机的Z轴设置为-cachedCamera.orthographicSize,HitTestContext.cachedMainCamera设置为自己(不做这步操作会导致UI触电出问题,无法点击),生成Stage Camera的时候修改对应配置。
using UnityEngine;
namespace FairyGUI
{
/// <summary>
/// Stage Camera is an orthographic camera for UI rendering.
/// </summary>
[ExecuteInEditMode]
[AddComponentMenu("FairyGUI/UI Camera")]
public class StageCamera : MonoBehaviour
{
......
void OnScreenSizeChanged(int newWidth, int newHeight)
{
......
if (constantSize)
{
cachedCamera.orthographicSize = DefaultCameraSize;
upp = cachedCamera.orthographicSize * 2 / screenHeight;
}
else
{
upp = 0.02f;
cachedCamera.orthographicSize = screenHeight / 2 * UnitsPerPixel;
}
cachedTransform.localPosition = new Vector3(cachedCamera.orthographicSize * screenWidth / screenHeight, -cachedCamera.orthographicSize, -cachedCamera.orthographicSize);
......
}
/// <summary>
/// Check if there is a stage camera in the scene. If none, create one.
/// </summary>
public static void CheckMainCamera()
{
......
//HitTestContext.cachedMainCamera = Camera.main;
HitTestContext.cachedMainCamera = main;
}
/// <param name="name"></param>
/// <param name="cullingMask"></param>
/// <returns></returns>
public static Camera CreateCamera(string name, int cullingMask)
{
......
//camera.orthographic = true;
camera.orthographic = false;
camera.orthographicSize = DefaultCameraSize;
//camera.nearClipPlane = -30;
//camera.farClipPlane = 30;
camera.farClipPlane = DefaultCameraSize + 1;
......
}
}
}
然后在之前我们解析投影新增的GObject.cs上添加解析自定义旋转(UIRotation)与Z轴(PositionZ)的代码,如下
using UnityEngine;
using System;
namespace FairyGUI
{
public partial class GObject : EventDispatcher
{
......
bool mIs3DUI = false;
Vector3 mUIRotation = Vector3.zero;
float mPositionZ = 0;
public bool Is3DUI
{
get { return mIs3DUI; }
}
public Vector3 UIRotation
{
get { return mUIRotation; }
}
public float PositionZ
{
get { return mPositionZ; }
}
//call in AnalyUserDefineData
public virtual void CustomAction()
{
if (data != null && mIs3DUI && displayObject != null)
{
displayObject.cachedTransform.localEulerAngles = mUIRotation;
_z = mPositionZ;
}
}
//call in Setup_AfterAdd
public void AnalyUserDefineData(object data)
{
if (data != null && !"".Equals(data.ToString()))
{
string[] args = data.ToString().Split('|');
foreach(string arg in args)
{
string[] keyvalue = arg.Split(':');
if (keyvalue.Length != 2)
{
continue;
}
......
if (keyvalue[0].Equals("UIRotation"))
{
mIs3DUI = true;
string[] array = keyvalue[1].Split(',');
mUIRotation = new Vector3(float.Parse(array[0]), float.Parse(array[1]), float.Parse(array[2]));
}
if (keyvalue[0].Equals("PositionZ"))
{
mPositionZ = float.Parse(keyvalue[1]);
}
}
CustomAction();
}
}
}
}
最后还需要注意的是,需要设置RenderMode为WorldSpace,否则一样会影响UI的触电导致无法点击。
果然用的UIPanel则直接在UIPanel上设置,用GRoot的话初始化的时候设置
GRoot.inst.container.renderMode = RenderMode.WorldSpace;