- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在现代Unity3D中,我们使用IPointerDownHandler调用家族。
关于IPointerDownHandler
系列通话,
public class FingerMove:MonoBehaviour, IPointerDownHandler...
{
public void OnPointerDown (PointerEventData data)
{
他们当然很棒
//
// example of programming a pinch (as well as swipes) using modern Unity
//
// here we are forced to track "by hand" in your own code
// how many fingers are down and which
// fingers belong to you etc etc:
//
// pedagogic example code:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEngine.EventSystems;
public class FingerMove:MonoBehaviour,
IPointerDownHandler, IDragHandler, IPointerUpHandler
{
// these three for the ordinary one-finger-only drag
private Vector2 prevPoint;
private Vector2 newPoint;
private Vector2 screenTravel;
// and this one is the ordinary one-finger-only drag
private int currentMainFinger = -1;
// and this for the (strictly second finger only) drag...
private int currentSecondFinger = -1;
private Vector2 posA;
private Vector2 posB;
private float previousDistance = -1f;
private float distance;
private float pinchDelta = 0f;
public void OnPointerDown (PointerEventData data)
{
if (currentMainFinger == -1)
{
// this is the NEW currentMainFinger
currentMainFinger = data.pointerId;
prevPoint = data.position;
// and for the drag (if it becomes used)...
posA = data.position;
return;
}
if (currentSecondFinger == -1)
{
// this is the NEW currentSecondFinger
currentSecondFinger = data.pointerId;
posB = data.position;
figureDelta();
previousDistance = distance;
return;
}
Debug.Log("third+ finger! (ignore)");
}
public void OnDrag (PointerEventData data)
{
// handle single-finger moves (swipes, drawing etc) only:
if ( currentMainFinger == data.pointerId )
{
newPoint = data.position;
screenTravel = newPoint - prevPoint;
prevPoint = newPoint;
if (currentSecondFinger == -1)
{
Debug.Log("NO 2f");
_processSwipe(); // handle it your way
}
else
{
}
// and for two-finger if it becomes used next frame
// or is already being used...
posA = data.position;
}
if (currentSecondFinger == -1) return;
// handle two-finger (eg, pinch, rotate etc)...
if ( currentMainFinger == data.pointerId ) posA = data.position;
if ( currentSecondFinger == data.pointerId ) posB = data.position;
figureDelta();
pinchDelta = distance - previousDistance;
previousDistance = distance;
_processPinch(); // handle it your way
}
private void figureDelta()
{
// when/if two touches, keep track of the distance between them
distance = Vector2.Distance(posA, posB);
}
public void OnPointerUp (PointerEventData data)
{
if ( currentMainFinger == data.pointerId )
{
currentMainFinger = -1;
}
if ( currentSecondFinger == data.pointerId )
{
currentSecondFinger = -1;
}
}
private float sensitivity = 0.3f;
// in this example, the swipes/pinch affects these three calls:
public Changer orbitLR;
public Changer orbitUD;
public Changer distanceZ;
// initial values of those...
private float LR = -20f;
private float UD = 20f;
private float distanceCam = 5f;
private void _processSwipe()
{
// in this example, just left-right or up-down swipes
LR = LR + sensitivity * screenTravel.x;
UD = UD - sensitivity * screenTravel.y;
LR = Mathf.Clamp(LR, -150f, 30f);
UD = Mathf.Clamp(UD, 5f, 50f);
orbitLR.RotationY = LR;
orbitUD.RotationX = UD;
}
private void _processPinch()
{
// in this example, pinch to zoom
distanceCam = distanceCam - pinchDelta * 0.0125f;
distanceCam = Mathf.Clamp(distanceCam, 3f, 8f);
distanceZ.DistanceZ = distanceCam;
}
}
(请注意,请不要回答无法使用的旧版“Touches”系统。这是有关正常的现代Unity开发的。)
最佳答案
我不想回答自己的问题,但是经过大量的研究和专家的投入,以下是解决问题的唯一方法。
让我们总结一下:
1.实际上,您必须添加一个守护程序。因此,对于Pinch,只需将“PinchInputModule.cs”放到使用者对象上就可以了。
您可能会认为“如果不添加守护程序,它将无法自动运行”。但是-实际上,使用Unity自己的,您必须添加一个守护程序“TouchInput”系列。 (有时他们会自动添加,有时会忘记并且您必须这样做。)
很简单,自动魔术的“追逐”很愚蠢,算了吧。您必须添加一个守护程序。
2.您确实必须从IPointerDownHandler / etc继承继承,因为很简单地,Unity搞砸了,您无法在StandAloneInputModule中正确继承。复制和粘贴未编程。
简而言之,由于Unity搞砸了,因此无法继承StandAloneInputModule的子类化路径,这不是一个好的工程。您只需在新的守护程序中使用IPointerDownHandler / etc。下面对此进行更多讨论。
下面,我给出“单点触摸”和“捏”的示例。这些已准备就绪。您可以为其他情况(例如四点触摸等)编写自己的代码。因此,使用捏住守护程序(实际上只是将其放到有问题的对象上),然后可以很轻松地处理捏住:
public void OnPinchZoom (float delta)
{
_processPinch(delta);
}
很难看到它更容易。
FingerMove
。
/*
ISingleFingerHandler - handles strict single-finger down-up-drag
Put this daemon ON TO the game object, with a consumer of the service.
(Note - there are many, many philosophical decisions to make when
implementing touch concepts; just some issues include what happens
when other fingers touch, can you "swap out" etc. Note that, for
example, Apple vs. Android have slightly different takes on this.
If you wanted to implement slightly different "philosophy" you'd
do that in this script.)
*/
public interface ISingleFingerHandler
{
void OnSingleFingerDown (Vector2 position);
void OnSingleFingerUp (Vector2 position);
void OnSingleFingerDrag (Vector2 delta);
}
/* note, Unity chooses to have "one interface for each action"
however here we are dealing with a consistent paradigm ("dragging")
which has three parts; I feel it's better to have one interface
forcing the consumer to have the three calls (no problem if empty) */
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class SingleFingerInputModule:MonoBehaviour,
IPointerDownHandler,IPointerUpHandler,IDragHandler
{
private ISingleFingerHandler needsUs = null;
// of course that would be a List,
// just one shown for simplicity in this example code
private int currentSingleFinger = -1;
private int kountFingersDown = 0;
void Awake()
{
needsUs = GetComponent(typeof(ISingleFingerHandler)) as ISingleFingerHandler;
// of course, you may prefer this to search the whole scene,
// just this gameobject shown here for simplicity
// alternately it's a very good approach to have consumers register
// for it. to do so just add a register function to the interface.
}
public void OnPointerDown(PointerEventData data)
{
kountFingersDown = kountFingersDown + 1;
if (currentSingleFinger == -1 && kountFingersDown == 1)
{
currentSingleFinger = data.pointerId;
if (needsUs != null) needsUs.OnSingleFingerDown(data.position);
}
}
public void OnPointerUp (PointerEventData data)
{
kountFingersDown = kountFingersDown - 1;
if ( currentSingleFinger == data.pointerId )
{
currentSingleFinger = -1;
if (needsUs != null) needsUs.OnSingleFingerUp(data.position);
}
}
public void OnDrag (PointerEventData data)
{
if ( currentSingleFinger == data.pointerId && kountFingersDown == 1 )
{
if (needsUs != null) needsUs.OnSingleFingerDrag(data.delta);
}
}
}
将该守护进程与您的使用者
FingerMove
放到游戏对象上,然后将其忽略。就是现在
public class FingerMove:MonoBehaviour, ISingleFingerHandler
{
public void OnSingleFingerDown(Vector2 position) {}
public void OnSingleFingerUp (Vector2 position) {}
public void OnSingleFingerDrag (Vector2 delta)
{
_processSwipe(delta);
}
private void _processSwipe(Vector2 screenTravel)
{
.. move the camera or whatever ..
}
}
就像我说的,
/*
IPinchHandler - strict two sequential finger pinch Handling
Put this daemon ON TO the game object, with a consumer of the service.
(Note, as always, the "philosophy" of a glass gesture is up to you.
There are many, many subtle questions; eg should extra fingers block,
can you 'swap primary' etc etc etc - program it as you wish.)
*/
public interface IPinchHandler
{
void OnPinchStart ();
void OnPinchEnd ();
void OnPinchZoom (float gapDelta);
}
/* note, Unity chooses to have "one interface for each action"
however here we are dealing with a consistent paradigm ("pinching")
which has three parts; I feel it's better to have one interface
forcing the consumer to have the three calls (no problem if empty) */
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
public class PinchInputModule:MonoBehaviour,
IPointerDownHandler,IPointerUpHandler,IDragHandler
{
private IPinchHandler needsUs = null;
// of course that would be a List,
// just one shown for simplicity in this example code
private int currentFirstFinger = -1;
private int currentSecondFinger = -1;
private int kountFingersDown = 0;
private bool pinching = false;
private Vector2 positionFirst = Vector2.zero;
private Vector2 positionSecond = Vector2.zero;
private float previousDistance = 0f;
private float delta = 0f;
void Awake()
{
needsUs = GetComponent(typeof(IPinchHandler)) as IPinchHandler;
// of course, this could search the whole scene,
// just this gameobject shown here for simplicity
}
public void OnPointerDown(PointerEventData data)
{
kountFingersDown = kountFingersDown + 1;
if (currentFirstFinger == -1 && kountFingersDown == 1)
{
// first finger must be a pure first finger and that's that
currentFirstFinger = data.pointerId;
positionFirst = data.position;
return;
}
if (currentFirstFinger != -1 && currentSecondFinger == -1 && kountFingersDown == 2)
{
// second finger must be a pure second finger and that's that
currentSecondFinger = data.pointerId;
positionSecond = data.position;
FigureDelta();
pinching = true;
if (needsUs != null) needsUs.OnPinchStart();
return;
}
}
public void OnPointerUp (PointerEventData data)
{
kountFingersDown = kountFingersDown - 1;
if ( currentFirstFinger == data.pointerId )
{
currentFirstFinger = -1;
if (pinching)
{
pinching = false;
if (needsUs != null) needsUs.OnPinchEnd();
}
}
if ( currentSecondFinger == data.pointerId )
{
currentSecondFinger = -1;
if (pinching)
{
pinching = false;
if (needsUs != null) needsUs.OnPinchEnd();
}
}
}
public void OnDrag (PointerEventData data)
{
if ( currentFirstFinger == data.pointerId )
{
positionFirst = data.position;
FigureDelta();
}
if ( currentSecondFinger == data.pointerId )
{
positionSecond = data.position;
FigureDelta();
}
if (pinching)
{
if ( data.pointerId == currentFirstFinger || data.pointerId == currentSecondFinger )
{
if (kountFingersDown==2)
{
if (needsUs != null) needsUs.OnPinchZoom(delta);
}
return;
}
}
}
private void FigureDelta()
{
float newDistance = Vector2.Distance(positionFirst, positionSecond);
delta = newDistance - previousDistance;
previousDistance = newDistance;
}
}
将该守护程序放到您拥有服务使用者的游戏对象上。注意,“混合和匹配”绝对没有问题。在此示例中,让我们同时进行拖动和捏捏手势。就是现在
public class FingerMove:MonoBehaviour, ISingleFingerHandler, IPinchHandler
{
public void OnSingleFingerDown(Vector2 position) {}
public void OnSingleFingerUp (Vector2 position) {}
public void OnSingleFingerDrag (Vector2 delta)
{
_processSwipe(delta);
}
public void OnPinchStart () {}
public void OnPinchEnd () {}
public void OnPinchZoom (float delta)
{
_processPinch(delta);
}
private void _processSwipe(Vector2 screenTravel)
{
.. handle drag (perhaps move LR/UD)
}
private void _processPinch(float delta)
{
.. handle zooming (perhaps move camera in-and-out)
}
}
就像我说的
public class FingerStretch:MonoBehaviour, IFourCornerHandler
{
public void OnFourCornerChange (Vector2 a, b, c, d)
{
... amazingly elegant solution
... Gökhan does all the work in FourCornerInputModule.cs
... here I just subscribe to it. amazingly simple
}
这只是一个令人难以置信的简单方法。
EventSystem
和
StandAloneInputModule
的游戏对象
SingleFingerInputModule.cs
代码中,我们非常明智地-当然-使用现有的惊人的IPointerDownHandler等功能,Unity已经完成了此功能我们(实质上)是“子类化”,添加了更多逻辑。您确实应该做的正是这件事。相反,如果您确实决定“制作类似于StandAloneInputModule的作品”,那将是一场惨败-您必须重新开始,可能会复制并粘贴Unity的源代码(用于IPointerDownHandler等),并以某种方式对其进行修改,当然是您永远不应该进行软件工程的确切示例。
public class Zoom:MonoBehaviour, ISingleFingerHandler, IPinchHandler
{
public void OnPinchZoom (float delta)
{
...
关于c# - 在现代Unity3D中捏和其他多指手势?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40341191/
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
我试图用这种形式简单地获取数字 28 integer+space+integer+integer+space+integer我试过这个正则表达式 \\s\\d\\d\\s 但我得到了两个数字11 和
最近一直在学习D语言。我一直对运行时感到困惑。 从我能收集到的关于它的信息中,(这不是很多)我知道它是一种有助于 D 的一些特性的运行时。像垃圾收集一样,它与您自己的程序一起运行。但是既然 D 是编译
想问一下这两个正则表达式有区别吗? \d\d\d 与 \d{3} 我已经在我的本地机器上使用 Java 和 Windows 操作系统对此进行了测试,两者都工作正常并且结果相同。但是,当在 linux
我正在学习 Go,而且我坚持使用 Go 之旅(exercise-stringer.go:https://tour.golang.org/methods/7)。 这是一些代码: type IPAddr
我在Java正则表达式中发现了一段令我困惑的代码: Pattern.compile( "J.*\\d[0-35-9]-\\d\\d-\\d\\d" ); 要编译的字符串是: String string
我在 ruby 代码上偶然发现了这个。我知道\d{4})\/(\d\d)\/(\d\d)\/(.*)/是什么意思,但是\1-\2-\3-\4 是什么意思? 最佳答案 \1-\2-\3-\4 是 b
我一直在努力解决这个问题,这让我很恼火。我了解 D 运行时库。它是什么,它做什么。我也明白你可以在没有它的情况下编译 D 应用程序。就像 XoMB 所做的那样。好吧,XoMB 定义了自己的运行时,但是
我有两个列表列表,子列表代表路径。我想找到所有路径。 List> pathList1 List> pathList2 当然是天真的解决方案: List> result = new ArrayList>
我需要使用 Regex 格式化一个字符串,该字符串包含数字、字母 a-z 和 A-Z,同时还包含破折号和空格。 从用户输入我有02-219 8 53 24 输出应该是022 198 53 24 我正在
目标是达到与this C++ example相同的效果: 避免创建临时文件。我曾尝试将 C++ 示例翻译为 D,但没有成功。我也尝试过不同的方法。 import std.datetime : benc
tl;dr:你好吗perfect forwarding在 D? 该链接有一个很好的解释,但例如,假设我有这个方法: void foo(T)(in int a, out int b, ref int c
有什么方法可以在 D 中使用abstract auto 函数吗? 如果我声明一个类如下: class MyClass { abstract auto foo(); } 我收到以下错误: mai
有没有人为内存中重叠的数组切片实现交集?算法在没有重叠时返回 []。 当 pretty-print (使用重叠缩进)内存中重叠的数组切片时,我想要这个。 最佳答案 如果您确定它们是数组,那么只需取 p
我已经开始学习 D,但我在使用 Andrei Alexandrescu 所著的 The D Programming Language 一书中提供的示例时遇到了一些麻烦。由于 int 和 ulong 类
如何创建一个不可变的类? 我的目标是创建一个实例始终不可变的类。现在我只是用不可变的方法和构造函数创建了一个“可变”类。我将其称为 mData,m 表示可变。然后我创建一个别名 alias immut
不久前我买了《The D Programming Language》。好书,很有教育意义。但是,我在尝试编译书中列出的语言功能时遇到了麻烦:扩展函数。 在这本书中,Andrei 写了任何可以像这样调用
我在 D http://www.digitalmars.com/d/2.0/lazy-evaluation.html 中找到了函数参数的惰性求值示例 我想知道如何在 D 中实现可能的无限数据结构,就像
这个问题在这里已经有了答案: 12 年前关闭。 Possible Duplicate: Could anyone explain these undefined behaviors (i = i++
当前是否可以跨模块扫描/查询/迭代具有某些属性的所有函数(或类)? 例如: source/packageA/something.d: @sillyWalk(10) void doSomething()
我是一名优秀的程序员,十分优秀!