需求:实现将3D模型显示在2DUI上面,实现王者荣耀英雄商城之中英雄展示功能,3D模型可以旋转,添加特效等正常3D功能。
-
使用RenderTexture和RawImage做相机映射
-
使用ScreenSpace Camera渲染摄像机
-
使用世界空间的UI和模型绑定
使用RenderTexture 和RawImage做相机映射
效果:
那些黑圈圈就是例子特效哦。
实现:
- Project面板创建一个RawImage
- 创建一个Camera,通过设置渲染模式控制模型显示的
- 创建一个RenderTexture
- 创建一个Cube,设置Layer为指定的布局,比如Model
- 将c创建的RenderTexture拖到a创建的RawImage的Texture属性里面
- 将c创建的RenderTexture拖到b创建的Camera的Target Texture属性里面
- 设置b创建的Camera的Clear Flags 为Solid Color,设置Background属性透明度为0
- 之后可以在Canvas里面设置a创建的RawImage的布局和大小来调整相应3D模型
优点:
可以多模型渲染,可以渲染包括粒子在内的各种3D模型,如果需要显示粒子特效,需要针对性开发对应Shader控制渲染混合方式(如:Blend One OneMinusSrcAlpha),可以再任何UI需要的地方显示,完全和UI一样,层级顺序,列表中显示模型,裁切等等都很方便。
缺点:
美术效果上,色差问题,和例子效果问题,局限性太大,模型数量不能太多,如果需要实现交互功能也比较麻烦,不能直接使用UI的交互逻辑,需要其他组件的配合,如果人物身上有一些特殊的效果,比如outline描边这样的,放在RenderTexture上就是达不到效果。
使用Screen Space Camera渲染摄像机
效果:
实现:
- 创建Canvas1,用来存放UI资源
- 创建Canvas2,用来存放3D模型资源,实现UI交互
- 将创建的两个Canvas的Render Mode设置为Screen Space –Camera
- 将两个Canvas的Render Camera设为同一个相机
- 通过调整Camera的Plane Distance控制哪个在前哪个在后面
优点:
模型可挂载在Canvas底下,也可以直接在场景中创建,调整大小位置,不影响模型本身的效果显示,和正常3D场景一样,模型本身完全不受限制。
缺点:
需要去控制Canvas的深度值,有很多问题实现不了,UI上盖模型,模型上盖UI,滑动列表中滑动裁切,需要和场景中模型做分离处理,不然容易混到一块分不清
使用世界空间的UI和模型绑定
实现:
- 创建Canvas
- 更改Canvas的RenderMode为WorldSpace
- 之后更改Canvas的大小和位置调整到3D模型的后面
优点:
UI完全跟3D组件一样,可以摆在任意位置和任意模型之后,自由度很大。
缺点:
UI交互功能很麻烦,UI无法适配屏幕大小显示,需要创建整体背景UI的时候还需要将新的Canvas设置为Screen Space Camera模式
在这个实现中比较重要的一点是如果透过UI将点击事件穿透下去,让模型也可以接受到点击事件,这时候我们就需要在UI上挂一个脚本,当接受到点击事件的时候调用PassEvent将事件传下去。
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections.Generic;
public class Test : MonoBehaviour,IPointerClickHandler ,IPointerDownHandler,IPointerUpHandler
{
//监听按下
public void OnPointerDown(PointerEventData eventData)
{
PassEvent(eventData,ExecuteEvents.pointerDownHandler);
}
//监听抬起
public void OnPointerUp(PointerEventData eventData)
{
PassEvent(eventData,ExecuteEvents.pointerUpHandler);
}
//监听点击
public void OnPointerClick(PointerEventData eventData)
{
PassEvent(eventData,ExecuteEvents.submitHandler);
PassEvent(eventData,ExecuteEvents.pointerClickHandler);
}
//把事件透下去
public void PassEvent<T>(PointerEventData data,ExecuteEvents.EventFunction<T> function)
where T : IEventSystemHandler
{
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(data, results);
GameObject current = data.pointerCurrentRaycast.gameObject ;
for(int i =0; i< results.Count;i++)
{
if(current!= results[i].gameObject)
{
ExecuteEvents.Execute(results[i].gameObject, data,function);
//RaycastAll后ugui会自己排序,如果你只想响应透下去的最近的一个响应,这里ExecuteEvents.Execute后直接break就行。
}
}
}
}
如有不准确之处,欢迎大家批评加改正哈。。。
参考链接:文章来源:https://www.toymoban.com/news/detail-431513.html
Unity3D研究院之将UI的点击事件渗透下去(九十) | 雨松MOMO程序研究院 (xuanyusong.com)文章来源地址https://www.toymoban.com/news/detail-431513.html
到了这里,关于Unity中如何通过UI显示3D模型解决方案?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!