先看一下效果

第一步

创建一个Shader脚本  赋值给材质球

Shader "UI/GuideMask"
{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 OffLighting OffZWrite OffZTest [unity_GUIZTestMode]Blend SrcAlpha OneMinusSrcAlphaColorMask [_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_ALPHACLIPstruct 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_ALPHACLIPclip (color.a - 0.001);#endif//-------------------add----------------------color.a*=(distance(IN.worldPosition.xy,_Center.xy) > _Silder);color.rgb*= color.a;//-------------------add----------------------return color;}ENDCG}}
}

第二步

写一个消息中心和单例

泛型单例

using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 泛型单例
/// </summary>
/// <typeparam name="T"></typeparam>
public class Singleton<T> where T : class, new()
{private static T instance;private static Object @object = new Object();public static T Instance{get{if (instance == null){lock (@object){instance = new T();}}return instance;}}
}

消息中心

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
/// <summary>
/// 消息中心
/// </summary>
public class MessageCenter : Singleton<MessageCenter>
{private Dictionary<int, Action<object[]>> dic = new Dictionary<int, Action<object[]>>();/// <summary>/// 侦听消息/// </summary>/// <param name="id"></param>/// <param name="action"></param>public void AddListerner(int id, Action<object[]> action){if (dic.ContainsKey(id)){dic[id] = dic[id] as Action<object[]> + action;}else{dic.Add(id, action);}}/// <summary>/// 消息广播/// </summary>/// <param name="id"></param>/// <param name="vs"></param>public void Brocast(int id, object[] vs){if (dic.ContainsKey(id)){Action<object[]> action = dic[id] as Action<object[]>;action?.Invoke(vs);}}
}

消息号

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public static class Define
{public const int ONE = 1;
}
写一个穿透事件的控制类
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System.Collections.Generic;
using System;
/// <summary>
/// 控制穿透
/// </summary>
public class EventPermeate : MonoBehaviour//, IPointerClickHandler,IPointerClickHandler,IPointerDownHandler
{// 事件穿透对象[HideInInspector]public GameObject target;监听按下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 (target == results[i].gameObject){// 如果是目标物体,则把事件透传下去,然后breakExecuteEvents.Execute(results[i].gameObject, data, function);MessageCenter.Instance.Brocast(Define.ONE, null);break;}}}
}
写一个Guide的镂空动画
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
/// <summary>
/// 新手引导动画
/// </summary>
[RequireComponent(typeof(EventPermeate))]
public class Guide : MonoBehaviour
{public Image[] targets; //存储指导图片private int index = 0; //下标private Material material; //材质private float diameter; // 直径private float current = 0f; //当前Vector3[] corners = new Vector3[4];void Awake(){MaskGuide(targets[index]);//target.GetComponent<EventPermeate>().OnPointerClick();}private void Start(){MessageCenter.Instance.AddListerner(Define.ONE, OnChangeGuid);}private void OnChangeGuid(object[] obj){index++;if(index< targets.Length){MaskGuide(targets[index]);}}/// <summary>/// 镂空遮罩/// </summary>/// <param name="target"></param>public void MaskGuide(Image target){// 设置事件透传对象gameObject.GetComponent<EventPermeate>().target = target.gameObject;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);}}/// <summary>/// 测试/// </summary>void OnGUI(){if (GUILayout.Button("Test")){index = 0;MaskGuide(targets[index]);}}Vector2 WordToCanvasPos(Canvas canvas, Vector3 world){Vector2 position = Vector2.zero;RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, world, canvas.GetComponent<Camera>(), out position);return position;}
}

第三步

UI界面的配置

1、创建一个Image命名为guide_mask然后添加Guide脚本

2、把Image的颜色设置为黑色,Alpha透明度拉半就OK

配置完成后 启动看效果就行了  (tips)左上角会有测试按钮

谢谢观看--

Unity功能开发 新手引导相关推荐

  1. [转] unity功能开发——实名认证

    前言 首先给大家介绍一下游戏实名认证. 网游实名制全称网络游戏实名制,是针对网络游戏的,玩家玩网络游戏时,需要输入真实的身份信息的制度. 要求用户使用有效身份证件实名注册,并保护用户注册信息,不得为使 ...

  2. Unity功能开发之_(单选、多选、框选)

    using System; using UnityEngine; using System.Collections; using System.Collections.Generic; using S ...

  3. java好友系统_unity功能开发——好友系统

    前言 游戏中设计好友系统主要目的是增加游戏的互动性 问题 首先介绍一下好友系统的功能: 1.好友列表展示: 2.添加好友:删除好友:一键操作等: 3.黑名单: 4.同意好友申请:拒绝好友申请: 解决 ...

  4. Unity初学者课堂—助手游戏局部功能开发讲解之开始游戏倒计时

    Unity初学者课堂-助手游戏局部功能开发讲解之开始游戏倒计时 学习闲言 游戏开始倒计时 地址栏qq后面号码非本人号码,避免误解已搬家至https://blog.csdn.net/weixin_403 ...

  5. Unity SteamVR插件详解:SteamVR Controller脚本分析+Vive控制器功能开发 ——转自波波...

    看到一篇很好的Steam VR脚本的详细解析文章,为了方便自己以后找得到,特意转载了. 大家都知道现在基于Unity开发Vive的应用程序都需要用到SteamVR这个插件,接下来的系列会重点分析该插件 ...

  6. 【功能开发篇】游戏中的时间系统修改Unity自带组件运行速度

    "功能开发篇"系列文章记录了我在平时工作中遇到的问题以及一些和游戏功能相关的项目经验. 目录 1. 插件介绍 2. 核心类功能拆解 3. Timeline深入 修改Rigidbod ...

  7. Unity客户端开发面试题记录

    Unity客户端开发面试题记录 1.如何理解面向对象思想 A:面向对象是将功能等通过对象来实现,将功能封装进对象之中,让对象去实现具体的细节.面向对象的特征是:封装,继承,多态.多态就是接口的多种不同 ...

  8. (完结)Unity游戏开发——新发教你做游戏(七):Animator控制角色动画播放

    文章目录 一.前言 二.Animator状态机组织 三.过渡条件 四.用代码设置过渡条件,触发动画播放 五.CharacterAniLogic.cs完整代码 一.前言 文章列表 Unity游戏开发-- ...

  9. Unity iPhone开发入门

    可能开发iphone的同学不多,但里面讲到的一些优化思路同样也能适用于pc开发,大家可以借鉴.本人翻译水平有限,欢迎指正呵呵! Unity iPhone开发入门 (一) 为iPhone开发 为iPho ...

  10. 如何在Unity上开发Nintendo(任天堂)Switch平台游戏时让游戏patch包大小尽量小

    如何在Unity上开发Nintendo(任天堂)Switch平台游戏时让游戏patch包大小尽量小 众所周知,Nintendo Switch有一条guidline-0123来限制游戏的patch包大小 ...

最新文章

  1. 欧式聚类分割并可视化
  2. 《Python基础教程第二版》第五章-条件、循环和其他语句(一)
  3. msb Lesson00_Object_Class.scala
  4. Delphi2009下编译提示“无法找到“Excel_TLB”
  5. headerIP php_PHP curl伪造IP地址和header信息代码实例
  6. idou老师教你学Istio 27:解读Mixer Report流程
  7. VueJS实现用户管理系统
  8. vs 编译设置obj路径_编译、连接
  9. 问题五十一:怎么用ray tracing画tear drop
  10. 引用服务器js文件写法,Vue 公共js文件如何放在服务器上引用
  11. js ajax异步提交,jquery ajax异步提交表单数据的方法
  12. html空格折叠原因,html – 使用Bootstrap列折叠空白
  13. Js逆向教程-05明确js逆向的目标
  14. key去掉下划线自动大写首字母工具类
  15. 服务器常用语言,计算机常用词汇--语言及服务器篇
  16. stream filter 多条件筛选
  17. mysql别名_MySQL设置别名
  18. printf与fprintf函数的区别
  19. 深信服上网行为管理开启snmp_深信服上网行为管理部署方式及功能实现配置说明...
  20. Vcc、Vee、Vdd、Vss傻傻分不清楚?

热门文章

  1. intel I2C的速率配置
  2. 老男孩学习Day05
  3. 区块链技术为版权保护与运营提供科技支撑
  4. 嵌入式Linux驱动开发
  5. 关于内点定义不同的讨论
  6. 微信营销是短暂的狂欢
  7. 正在此计算机上搜索更新,安装win10过程中一直在检测更新的解决办法
  8. 原来都是freesync惹的锅
  9. 现在世界上有多少种操作系统?简要介绍
  10. 扔硬币(快速幂+组合数)