UG4L16——插入模型、粒子、Canvas

本章代码关键字

1
2
3
4
GoWarpper                    //游戏对象包装器,通过该对象可以将某个Unity3D对象包装显示在一个空白图形上
goWrapper.CacheRenderers() //更新包装对象的显示,当被GoWarpper包装的游戏对象变化时,需要调用该方法来更新其在UI上的显示
goWrapper.wrapTarget //设置包装对象,可以更换显示的模型或者例子,更换时如果要释放旧对象,需要自己手动销毁
goWrapper.SetWrapTarget() //设置包装对象,可以更换显示的模型或者例子,第二个参数可以设置是否复制材质,更换时如果要释放旧对象,需要自己手动销毁

UI中插入3D对象或者粒子

注意:这种方法的缺点是在UI摄像机下3D对象没有透视,如果想要有透视,可以使用Render Texture的方式
可以参考:UG3L15——模型和粒子显示在UI之前Render Texture

  1. 创建3D对象

    1
    2
    //创建3D对象
    GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
  2. 设置3D对象的相对坐标,缩放,旋转 (注意:缩放比为100:1)

    1
    2
    3
    4
    5
    6
    //创建3D对象
    GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
    //设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
    obj.transform.localPosition = Vector3.zero;
    obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放大100倍
    obj.transform.localEulerAngles = Vector3.zero;
  3. 在UI中放置一个空白的图形获取它

    image

  4. 创建一个GoWrapper​对象,放入到图形中,使用gGraph.SetNativeObject()​放置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    //创建3D对象
    GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
    //设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
    obj.transform.localPosition = Vector3.zero;
    obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放大100倍
    obj.transform.localEulerAngles = Vector3.zero;
    //创建一个GoWrapper对象,放入到面板下的空白图形中
    TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
    GoWrapper wrapper = new GoWrapper(obj); //将创建的3d对象传入到GoWrapper的构造函数内
    panel.m_pos3D.SetNativeObject(wrapper); //将图形添加一个原生对象,传入由GoWrapper包装的游戏对象

显示效果:image

点击3D对象或者粒子

GoWrapper​默认没有大小,所以不能处理点击事件,
如果想要被点击,可以在3D对象显示区域添加一个透明度为0的图形作为点击区域或者一个空组件
通过他们来监听点击

image

1
2
3
4
5
6
7
8
9
10
11
12
13
14
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放大100倍
obj.transform.localEulerAngles = Vector3.zero;
//创建一个GoWrapper对象,放入到面板下的空白图形中
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
GoWrapper wrapper = new GoWrapper(obj); //将创建的3d对象传入到GoWrapper的构造函数内
panel.m_pos3D.SetNativeObject(wrapper); //将图形添加一个原生对象,传入由GoWrapper包装的游戏对象
//添加监听事件
panel.m_click3D.onClick.Add(() =>
{
print("3D对象被点击");
});

输出:image

通过UIPanel进行调试

通过上述代码创建3D物体不方便调试,或者说不能即时的调整3D物体的位置和旋转缩放
我们可以利用 UIPanel 勾选它的 Set Native Children Order
然后放置3D物体或者粒子 把数据记录好 然后来改代码当中的数据

image

image

还可以调整Z轴,确认该3D对象是否显示在UI对象之上

更新对象状态

GoWrapper​会在构造函数里查询你的GameObject​里所有的Renderer​并保存
如果你的GameObject后续发生了改变,需要告知GoWrapper重新查询和保存,否则显示不正确

1
2
3
4
5
6
7
8
9
10
11
12
13
//创建3D对象
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放大100倍
obj.transform.localEulerAngles = Vector3.zero;
//创建一个GoWrapper对象,放入到面板下的空白图形中
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
GoWrapper wrapper = new GoWrapper(obj); //将创建的3d对象传入到GoWrapper的构造函数内
panel.m_pos3D.SetNativeObject(wrapper); //将图形添加一个原生对象,传入由GoWrapper包装的游戏对象

obj.transform.localEulerAngles = new Vector3(0, 45, 0);
wrapper.CacheRenderers();

显示效果:image

更换显示的3D对象或者粒子

需要先把之前的对象删了,在对goWrapper.wrapTarget​关联新的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//创建3D对象
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放到100倍
obj.transform.localEulerAngles = Vector3.zero;
//创建一个GoWrapper对象,放入到面板下的空白图形中
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
GoWrapper wrapper = new GoWrapper(obj); //将创建的3d对象传入到GoWrapper的构造函数内
panel.m_pos3D.SetNativeObject(wrapper); //将图形添加一个原生对象,传入由GoWrapper包装的游戏对象
//更换显示的3D对象或者粒子
Destroy(obj); //删除之前的对象
obj = GameObject.CreatePrimitive(PrimitiveType.Sphere);
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放大100倍
obj.transform.localEulerAngles = Vector3.zero;
wrapper.wrapTarget = obj; //将要替换的3d对象赋值给gowrapper的包装属性上

显示效果:image

材质的复用

如果你想通过UI上的一些操作改变一个模型的材质,但是这个模型在场景中也使用了,如果在UI上改了场景上的也会被修改
这是因为他们使用的是共享材质,如果你不想UI上对模型的修改影响场景上的模型 可以使用复制材质

在对GoWrapper​设置一个3D对象时,需要使用SetWrapTarget()​方法,第二个参数传入true​,表示使用复制材质

1
2
3
4
5
6
7
8
9
10
//创建3D对象
GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);
//设置3D对象的相对位置,缩放,旋转(注意!缩放比100:1)
obj.transform.localPosition = Vector3.zero;
obj.transform.localScale = Vector3.one * 100; //缩放比是100:1,因此要放到100倍
obj.transform.localEulerAngles = Vector3.zero;
//创建一个GoWrapper对象,放入到面板下的空白图形中
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
GoWrapper wrapper = new GoWrapper();
wrapper.SetWrapTarget(obj, true);

UI中插入UGUI的Canvas(不建议)

  1. 设置Canvas​的Render Mode为WorldSpace,Event Camera为Stage Camera。
  2. 删除Canvas Scaler组件(如果有)
  3. 使用GoWrapper​包装Canvas