美文网首页Unity干货unity3D技术分享Unity好用插件收集
Unity 之大屏幕多点触控插件 TouchScript 9.0

Unity 之大屏幕多点触控插件 TouchScript 9.0

作者: su9257_海澜 | 来源:发表于2018-04-26 18:11 被阅读415次

    在端游上大家应该多数都使用过的EasyTouch插件,在EasyTouch 5.0.17 最新版本扩展方法中我有过简单的介绍,今天说一下另一款触摸插件,它非常适合做展示类大屏幕的多点触控TouchScript,在Unity上的AssetStore也是五星好评,而且还是免费资源,也可以在GitHub上下载对应的TouchScript

    场景初始化,创建一个空的场景把对应的Cursors和TouchManger拖入到场景中,点击Play运行场景,就会出现对应的效果


    然后创建一个Cube 并在其gameobject上添加两个组件 TransformGesture与Transformer,Transformer负责监听TransformGesture的事件并把响应的事件应用到GameObject上,

    当然也可以使用快捷热键Alt,按住Alt点击物体,然后再次点击物体就会出现第二个出点,可以使用旋转个缩放效果

    下面我们开始介绍TouchScript提供的每一个Example

    第一个示例场景Camera

    Camera.gif
    这个例子演示了如何使用
    • ScreenTransformGesture
    • Pointer limits
    • FullscreenLayer
    相互作用
    • 用一根手指拖动相机
    • 用2个手指拖动旋转相机
    • 捏缩放
    • 用2个手指旋转绕Z轴旋转

    在这个场景中主要含有 主要逻辑和3个TouchScript组件

    1. FullscreenLayer ---在这个图层中,你可以看到所有的 pointers 而不需要对场景进行任何raycast投射然后将目标设置为它所连接的GameObject,在这个例子中, FullscreenLayer 通常放在层次结构的底部以捕获所有剩余的pointer,但在本例中,它是唯一的层,因为我们对“Touching”任何对象不感兴趣。

    我对他的理解为这个FullscreenLayer 只是接受TouchScript射线的一个层级,一般会把这个层级放在最底层,类似于背景,如果有其他层级在它前面会挡住摄像,然后对应的层级处理响应的事件,这个场景中只有这个层级,所以其他物理无法接受事件所以不会有操作

    2. ScreenTransformGesture 将Transform Type设置为“Translation”并将Limit Pointers限制为1.此手势仅识别单指针平移移动。
    3. 另一个ScreenTransformGesture,它具有Transform Type 设置为Translation、Rotation、Scaling和Limit Pointers to> = 2。 该手势可识别所有双指针变换。
    4. CameraController脚本订阅ScreenTransformGestures并控制相机移动,如下所示:
    /*
     * @author Valentin Simonov / http://va.lent.in/
     */
    
    using UnityEngine;
    using TouchScript.Gestures.TransformGestures;
    
    namespace TouchScript.Examples.CameraControl
    {
        /// <exclude />
        public class CameraController : MonoBehaviour
        {
            public ScreenTransformGesture TwoFingerMoveGesture;
            public ScreenTransformGesture ManipulationGesture;
            /// <summary>
            /// 移动速度
            /// </summary>
            public float PanSpeed = 200f;
            /// <summary>
            /// 旋转速度
            /// </summary>
            public float RotationSpeed = 200f;
            /// <summary>
            /// 缩放速度
            /// </summary>
            public float ZoomSpeed = 10f;
    
            private Transform pivot;
            private Transform cam;
    
            private void Awake()
            {
                pivot = transform.Find("Pivot");
                cam = transform.Find("Pivot/Camera");
            }
    
            private void OnEnable()
            {
                TwoFingerMoveGesture.Transformed += twoFingerTransformHandler;
                ManipulationGesture.Transformed += manipulationTransformedHandler;
            }
    
            private void OnDisable()
            {
                TwoFingerMoveGesture.Transformed -= twoFingerTransformHandler;
                ManipulationGesture.Transformed -= manipulationTransformedHandler;
            }
            /// <summary>
            /// 单指事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void manipulationTransformedHandler(object sender, System.EventArgs e)
            {
                var rotation = Quaternion.Euler(ManipulationGesture.DeltaPosition.y / Screen.height * RotationSpeed,
                    -ManipulationGesture.DeltaPosition.x / Screen.width * RotationSpeed,
                    ManipulationGesture.DeltaRotation);
                pivot.localRotation *= rotation;
                cam.transform.localPosition += Vector3.forward * (ManipulationGesture.DeltaScale - 1f) * ZoomSpeed;
            }
            /// <summary>
            /// 双指事件
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void twoFingerTransformHandler(object sender, System.EventArgs e)
            {
                pivot.localPosition += pivot.rotation * TwoFingerMoveGesture.DeltaPosition * PanSpeed;
            }
        }
    }
    

    第二个示例场景Checkers

    Checkers

    这个例子演示了如何使用

    • TransformGesture
    • PinnedTransformGesture
    • PinnedTransformGesture
    • OverHelper
    • StandardLayer
    • GestureManager.Instance.GlobalGestureDelegate

    相互作用

    • 拖动一个棋子来移动它
    • 拖动板来旋转它
    • 按住Space持续禁用所有的手势,但有一个除外(发光棋子)

    说明

    /Scene/Camera GameObject有一个StandardLayer 禁用了所有选项,但是Hit 3D Objects在Hit test options属性中仅对场景中的3D对象进行光线投射,因为此场景没有任何2D或UI对象。

    /Scene/ Board GameObject有两个附件:

    1. PinnedTransformGesture 具有Transform Type设置为Rotation与投影到XZ Plane这是地平面。这意味着这个gesture会将屏幕pointers投影到这个平面上并计算这个平面内的所有变换。(平面拖拽)
    2. Board 脚本监听到PinnedTransformGesture的事件和棋盘的旋转,如下所示:
    /*
     * @author Valentin Simonov / http://va.lent.in/
     */
    
    using UnityEngine;
    using TouchScript.Gestures.TransformGestures;
    
    namespace TouchScript.Examples.Checkers
    {
        /// <exclude />
        public class Board : MonoBehaviour
        {
            private PinnedTransformGesture gesture;
    
            private void OnEnable()
            {
                gesture = GetComponent<PinnedTransformGesture>();
                gesture.Transformed += transformedHandler;
            }
    
            private void OnDisable()
            {
                gesture.Transformed -= transformedHandler;
            }
    
            private void transformedHandler(object sender, System.EventArgs e)
            {
                transform.localRotation *= Quaternion.AngleAxis(gesture.DeltaRotation, gesture.RotationAxis);
            }
        }
    }
    

    /Scene/Board/Container/CheckerDark GameObjects(棋子) 附有以下组件:

    1. TransformGesture 具有 Transform Type set to Translation 投影到XZ Plane
    2. Transformer 它会监听TransformGesture的事件和移动对象。
    3. OverHelper 在指针位于对象上方时调度事件。(一句话就是判断是否鼠标悬停,插件自带)
    4. Highlight 显示哪些侦听OverHelper事件并更改对象颜色。
    5. Checker 监听TransformGesture的事件并在此对象上禁用或启用Rigidbody,而实际移动由Transformer组件完成。

    /Scene gameobject 具有附加到它的Exclusive组件,它实现了IGestureDelegate接口并将它自己分配给它GestureManager.Instance.GlobalGestureDelegate。当用户按下Space此组件时,这个组件阻止所有的手势开始,除了目标gameobject上的那些手势:

            public bool ShouldReceivePointer(Gesture gesture, Pointer pointer)
            {
                if (exclusive) return gesture == Target;
                Debug.Log("点击到物体");
                return true;
            }
            public bool ShouldBegin(Gesture gesture)
            {
                if (exclusive) return gesture == Target;
                Debug.Log("开始操作物体");
                return true;
            }
    
            public bool ShouldRecognizeSimultaneously(Gesture first, Gesture second)
            {
                Debug.Log("ShouldRecognizeSimultaneously");
                Debug.Log(first);//打印结果:CheckerLight(TouchScript.Gestures.TransformGestures.TransformGesture)
                Debug.Log(second);//打印结果:Board (TouchScript.Gestures.TransformGestures.PinnedTransformGesture)
                return false;
            }
    

    第三个示例场景Color

    这个例子演示了如何使用

    • 操作2D对象
    • Gesture.Cancel()取消一个手势并将其指针返回给系统。

    操作

    • 拖动圆圈。重叠时,它们会产生另一个组合的圆圈,
    • 用两个手指来缩放圆圈。

    说明

    / Scene / Camera GameObject有一个StandardLayer,禁用了所有选项,但是Hit 2D Objects在Hit test options属性中仅对场景中的2D对象进行raycast 投射,因为此场景没有任何3D或UI对象。

    Circle预制件附有以下组件:

    1. TransformGesture Transform Type 设置为Everything使用户可以移动,缩放和旋转圆(虽然旋转圈并没有真正多大意义)。

    2. Transformer 它会监听TransformGesture的事件。

    3. Circle 其处理圆相交于OnTriggerEnter2D并使用该代码来取消当前活动TransformGesture:

    GetComponent<TransformGesture>().Cancel(true, true);
    

    (true,true)意味着指针应该返回到系统,就像刚刚按下的那样。此时取消的指针会被新的(更大的)圆圈及其TransformGesture捕捉,因此用户可以继续移动并调整新圆圈的大小。

    第四个示例场景Cube

    这个例子演示了如何使用

    • TouchLayer.Delegate
    • 实现自定义输入源

    相互作用

    拖动,缩放,旋转猫的图片。

    注意你是如何触摸立方体的,但是能够将图像移到场景中很远的地方。

    说明

    这个例子展示了TouchScript的可扩展性。场景中有一个立方体,其中有一个RenderTexture来自指定给其材质的离屏相机。但您仍然可以用手指移动和调整此图像的大小。

    /Scene/Scene Camera/Image GameObject具有TransformGesture和Transformer组件来移动它。这是您在立方体上看到的图像。

    / Scene / Cube GameObject附有以下组件:

    1. MetaGesture捕获对象的指针并分派事件。

    2. RedirectInput监听MetaGesture的事件。但是它也继承了InputSource它的意思,它可以向系统中注入指针。它是这样做的:

    如果此指针由此脚本生成,请停止处理它。

    private void pointerPressedHandler(object sender, MetaGestureEventArgs metaGestureEventArgs)
    {
        var pointer = metaGestureEventArgs.Pointer;
        if (pointer.InputSource == (IInputSource)this) return;
    

    接下来,代码创建一个复制指针,添加FLAG_INTERNAL以隐藏它Cursor Visualizer,然后添加并按下它。此时触摸被注入到系统中。

        var  newPointer = PointerFactory.Create(pointer.Type,this);
        newPointer.CopyFrom(pointer);
        newPointer.Position = processCoords(pointer.GetPressData()。RaycastHit.textureCoord);
        newPointer.Flags = pointer.Flags | Pointer.FLAG_ARTIFICIAL | Pointer.FLAG_INTERNAL;
        addPointer(newPointer);
        pressPointer(newPointer);
        map.Add(pointer.Id,newPointer);
    }
    

    /Scene GameObject附有以下组件:

    1. LayerDelegate实现jiekou ILayerDelegate并TouchLayer.Delegate通过Init脚本设置为场景中的所有图层。

    2. Init设置LayerDelegate。

    这是LayerDelegate中的代码:

    public RedirectInput Source;
    public TouchLayer RenderTextureLayer;
    
    public bool ShouldReceivePointer(TouchLayer layer, IPointer pointer)
    {
        if (layer == RenderTextureLayer)
            return pointer.InputSource == (IInputSource)Source;
        return pointer.InputSource != (IInputSource)Source;
    }
    

    中心思想就是:“RenderTexture相机上的图层应该接收虚假指针,而其他人则不会”。

    第五个示例场景:Multiuser(多用户)

    这个例子演示了如何使用

    • Multiple layers
    • TapGesture

    相互作用

    * 拖动屏幕的一半,
    * 拖动跳棋,
    * 拖动板来旋转它们,
    * 点击Unity标志。

    说明

    场景包含5层。检查附有TouchManager脚本的TouchManager的gameobjectt,其中包含图层列表。图层必须按特定顺序排序:2D,右摄像机层和左3D摄像机层,右全屏层和左全屏图层。这是因为在尝试确定指针命中的对象时,层从上到下进行迭代。

    / Scene / 2D / Unity_Logo GameObjects上有TapGesture,由Logo组件用来改变水龙头的颜色。
    / Scene / Left / Board和/ Scene / Right / Board与Checkers示例中的相同。

    第六个示例场景:Photos

    这个例子演示了如何使用
    * 使用UI控件
    * PressGesture
    * TransformGesture and Transformer
    相互作用
    * 移动,缩放和旋转照片
    * 点击添加按钮添加照片
    * 点击彩色按钮来改变颜色。

    说明

    / Scene / World Space Plane / World Space Canvas / Field / Image# GameObjects附有以下组件:
    1. TransformGesture和Transformer移动/缩放/旋转猫的图像。
    2. PressGesture用于使被按下的图像向上。
    / Scene / World Space Plane / World Space Canvas / Field / Image#/ Close只是TouchScript发送指针输入的UI按钮。
    /Scene/ScreenSpace Canvas/Panel/Button只是一组与UI交互的UI按钮。不需要特殊的组件或代码。

    第七个示例场景:Portal

    这个例子演示了如何使用

    1. Gesture.Cancel()
    2. TransformGesture和Transformer,
    3. LayerManager.SetExclusive()

    相互作用

    按Unity标志来产生一个星球
    将一颗行星拖入入口。

    说明 此示例演示如何执行以下操作:

    1. 在某些情况下取消gesture ,
    2. “给”从一个对象到另一个对象的pointers 。
    /Game Canvas/Spawner# GameObjects 附有以下组件:
    1. Presswesture由Spawner使用。
    2. Spawner在按下徽标时创建一个行星,并通过执行以下操作从PressGesture“给出”它的pointer :
    var target = Instantiate(Prefab, Position.parent);
    target.position = Position.position;
    LayerManager.Instance.SetExclusive(target);
    press.Cancel(true, true);
    LayerManager.Instance.ClearExclusive();
    
    此代码创建一个实例Prefab并将其设置为exclusive ,因此没有其他对象可以接收pointers。之后,代码取消gesture并将其pointers 返回到立即转到我们的对象的系统。
    /Scene/Camera/Stuff/Vortex附有一个脚本,可以planet.Fall(); 在每个行星靠近的地方调用。该方法基本上执行以下操作:
    var gesture = GetComponent<TransformGesture>();
    if (gesture != null) gesture.Cancel();
    

    它取消手势但不取消它的指针,所以如果用户没有很快抓住它们,飞机就会落入涡流中。

    第八个示例场景:RawInput

    这个例子演示了如何使用

    • 指针输入。
    相互作用
    • 触摸屏幕
    说明
    • 这个例子展示了如何使用没有手势逻辑的原始指针输入

    /Scene/Camera含有一个Spawner脚本,其派生使用此代码预制实例:

    private void OnEnable()
    {
        if (TouchManager.Instance != null)
            TouchManager.Instance.PointersPressed += pointersPressedHandler;
    }
    
    private void OnDisable()
    {
        if (TouchManager.Instance != null)
            TouchManager.Instance.PointersPressed -= pointersPressedHandler;
    }
    
    private void pointersPressedHandler(object sender, PointerEventArgs e)
    {
        foreach (var pointer in e.Pointers)
            spawnPrefabAt(pointer.Position);
    }
    

    第九个示例场景:Taps

    这个例子演示了如何使用

    • TapGesture,
    • LongPressGesture。
    相互作用
    • 双击表格来产生一个新的箱子,
    • 点击一个箱子踢它,
    • 拿着箱子把它炸掉。
    说明

    /Scene/Container/Cube的GameObjects附有以下组件:

    • LongPressGesture Break脚本使用LongPressGesture炸开立方体
    • PressGesture Press脚本用于启动补间颜色的PressGesture
    • TapGesture * Kick 脚本用于TapGesture*推动方块,
    • Kick which kicks the cube on tap,
    • Break破了立方体成8个个小立方体. 它显示了如何使用 StateChanged 事件:
    longPressGesture.StateChanged += longPressedHandler;
    
    private void longPressedHandler(object sender, GestureStateChangeEventArgs e)
    {
        if (e.State == Gesture.GestureState.Recognized)
        {
            ...
        }
        else if (e.State == Gesture.GestureState.Failed)
        {
            stopGrowing();
        }
    }
    

    我们StateChanged在这里使用事件而不是更简单,LongPressed因为我们需要处理GestureState.Failed

    /Scene/table_and_chair GameObject 有TapGesture组件,此组件附有Number of Taps Required设置为2和Limit Time(时间限制) 1秒。这意味着我们需要一个双选项卡,每次点击的最大时间间隔为1秒。Spawn组件使用TapGesture来产生新的立方体。

    相关文章

      网友评论

      • d44ac3b18aae:如何避免 在双指旋转的时候 双指缩放不同时作用
        su9257_海澜:@girl_1bff 双指的话只能动态取消旋转或者缩放其中一下,判断是哪个手势自行设定个阈值,比如一概开始0.5秒旋转的角度和手势的伸缩尺寸哪个大用哪个,兄弟,目前我能想到的就是这个
      • 224d19a305b2:楼主,当手指经过我们包含TransformGesture脚本的UI是触发不了他的拖拽的功能的。除非点击到我们的UI上,other.GetComponent<TransformGesture>().StateChanged += onDrag;请问有什么方法可以当手指从空白起点经过我们的UI的时候,出发他的手势拖拽功能
        su9257_海澜:他这个是基于射线检测然后确定物体、创建pointers,可以尝试在鼠标滑过的地方用射线检测是否触碰指定UI,然后创建动态pointers复制给对应的UI,不知道这个方法是否可行。关于传递pointers在第七个示例场景有演示。

      本文标题:Unity 之大屏幕多点触控插件 TouchScript 9.0

      本文链接:https://www.haomeiwen.com/subject/qskplftx.html