内容简介:UGUI研究院之新手引导事件上下分离(二十七)
新手引导最好和业务逻辑拆开,也就是做新手引导的 程序员 不能去影响到下面做系统的人。
1.开发一个新手引导编辑器,让策划配出每个引导的点击区域。
2.在Shader中扣一个洞。(圆形或者矩形)用来做显示的点击区域。
3.新手引导的进度需要与服务器进行同步,为了不影响到下面的业务逻辑,在最顶层将UI事件拦截后,渗透点击事件并且与服务器同步进度。渗透事件可以参考我之前的文章,Unity3D研究院之将UI的点击事件渗透下去(九十)
http://www.xuanyusong.com/archives/4241Drag摇杆的事件,需要把Begin Draging End都要渗透下去。按钮、列表中的Cell元素的点击事件需要特殊注意一下,因为要点击在Cell上,而不是最前面的UI上。
4.新手引导的出现条件,大部分都是打开某个UI并且拥有控制焦点,可能还有 等级/接任务/交任务/进场景 。可以将这些关键点作为事件抛出,在新手引导模块中处理即可。
5.强制引导需要注意,很有可能把玩家卡死。比如引导玩家进副本,请求进副本的消息,和请求新手引导进度的消息是两个不同的,那么就有一定概率出现一个发送成功,另一个发送不成功,如果此时又触发掉线,重进游戏估计就肯定就卡死了。 所以保险起见强制引导最好也可以让玩家跳过。(比如点击空白区域超过5次)
6.最后在分享一个UI的效果,周围是灰色蒙版,然后四周向点击区域聚合的动画。
先上代码。
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; /// <summary> /// 新手引导动画 /// </summary> public class Guide : MonoBehaviour { public Image target; private Vector4 center; private Material material; private float diameter; // 直径 private float current =0f; Vector3[] corners = new Vector3[4]; void Awake () { Canvas canvas = GameObject.Find ("Canvas").GetComponent<Canvas> (); target.rectTransform.GetWorldCorners (corners); diameter = Vector2.Distance (WordToCanvasPos(canvas,corners [0]), WordToCanvasPos(canvas,corners [2])) / 2f; float x =corners [0].x + ((corners [3].x - corners [0].x) / 2f); float y =corners [0].y + ((corners [1].y - corners [0].y) / 2f); Vector3 center = new Vector3 (x, y, 0f); Vector2 position = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, center, canvas.GetComponent<Camera>(), out position); center = new Vector4 (position.x,position.y,0f,0f); material = GetComponent<Image>().material; material.SetVector ("_Center", center); (canvas.transform as RectTransform).GetWorldCorners (corners); for (int i = 0; i < corners.Length; i++) { current = Mathf.Max(Vector3.Distance (WordToCanvasPos(canvas,corners [i]), center),current); } material.SetFloat ("_Silder", current); } float yVelocity = 0f; void Update () { float value = Mathf.SmoothDamp(current, diameter, ref yVelocity, 0.3f); if (!Mathf.Approximately (value, current)) { current = value; material.SetFloat ("_Silder", current); } } void OnGUI(){ if(GUILayout.Button("Test")){ Awake (); } } Vector2 WordToCanvasPos(Canvas canvas,Vector3 world){ Vector2 position = Vector2.zero; RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, world, canvas.GetComponent<Camera>(), out position); return position; } }
shader是在UI-Default的基础上改了,原理就是扣一个洞,修改每个点的颜色。 –add–是修改的代码。如果unity版本升级shader变化,把–add–中的代码加上即可。
Shader "UI/Default_Mask" { Properties { [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} _Color ("Tint", Color) = (1,1,1,1) _StencilComp ("Stencil Comparison", Float) = 8 _Stencil ("Stencil ID", Float) = 0 _StencilOp ("Stencil Operation", Float) = 0 _StencilWriteMask ("Stencil Write Mask", Float) = 255 _StencilReadMask ("Stencil Read Mask", Float) = 255 _ColorMask ("Color Mask", Float) = 15 [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 //-------------------add---------------------- _Center("Center", vector) = (0, 0, 0, 0) _Silder ("_Silder", Range (0,1000)) = 1000 // sliders //-------------------add---------------------- } SubShader { Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" "CanUseSpriteAtlas"="True" } Stencil { Ref [_Stencil] Comp [_StencilComp] Pass [_StencilOp] ReadMask [_StencilReadMask] WriteMask [_StencilWriteMask] } Cull Off Lighting Off ZWrite Off ZTest [unity_GUIZTestMode] Blend SrcAlpha OneMinusSrcAlpha ColorMask [_ColorMask] Pass { Name "Default" CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma target 2.0 #include "UnityCG.cginc" #include "UnityUI.cginc" #pragma multi_compile __ UNITY_UI_ALPHACLIP struct appdata_t { float4 vertex : POSITION; float4 color : COLOR; float2 texcoord : TEXCOORD0; UNITY_VERTEX_INPUT_INSTANCE_ID }; struct v2f { float4 vertex : SV_POSITION; fixed4 color : COLOR; float2 texcoord : TEXCOORD0; float4 worldPosition : TEXCOORD1; UNITY_VERTEX_OUTPUT_STEREO }; fixed4 _Color; fixed4 _TextureSampleAdd; float4 _ClipRect; //-------------------add---------------------- float _Silder; float2 _Center; //-------------------add---------------------- v2f vert(appdata_t IN) { v2f OUT; UNITY_SETUP_INSTANCE_ID(IN); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); OUT.worldPosition = IN.vertex; OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); OUT.texcoord = IN.texcoord; OUT.color = IN.color * _Color; return OUT; } sampler2D _MainTex; fixed4 frag(v2f IN) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); #ifdef UNITY_UI_ALPHACLIP clip (color.a - 0.001); #endif //-------------------add---------------------- color.a*=(distance(IN.worldPosition.xy,_Center.xy) > _Silder); color.rgb*= color.a; //-------------------add---------------------- return color; } ENDCG } } }
如下图所示,脚本挂在bg上,target就是点击区域的Image。
Play游戏就能看到动画效果。如下图所示,我们项目是有UI摄像机的,所以canvas和camera需要注意一下,有UI摄像机和没UI摄像机算区域是不同的。
OK ,这个方法我已经在项目中使用, 如果有什么想法或者建议欢迎在下面给我留言。
测试版本unity5.5.2
- 本文固定链接: http://www.xuanyusong.com/archives/4408
- 转载请注明:雨松MOMO 于雨松MOMO程序研究院 发表
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
捐 赠 如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Head First HTML5 Programming
Eric Freeman、Elisabeth Robson / O'Reilly Media / 2011-10-18 / USD 49.99
What can HTML5 do for you? If you're a web developer looking to use this new version of HTML, you might be wondering how much has really changed. Head First HTML5 Programming introduces the key featur......一起来看看 《Head First HTML5 Programming》 这本书的介绍吧!
URL 编码/解码
URL 编码/解码
XML、JSON 在线转换
在线XML、JSON转换工具