C# 使用Unity 5用户界面进行收缩缩放
我正在尝试在一个基于Unity UI的应用程序中重新实现一个从收缩到缩放的系统。大约六个月前,我通过将UI画布制作成常规游戏对象的子对象,并操纵该对象的变换,将其组合在一起,但自从更新到Unity 5.5+后,我发现这不起作用。我能得到的最近距离允许收缩手势更改画布的缩放因子,这a)会使图像、面板等根据其对齐方式不正确地调整大小,b)缩放后不允许平移 到目前为止,我得到的是:C# 使用Unity 5用户界面进行收缩缩放,c#,user-interface,unity3d,unity5,pinchzoom,C#,User Interface,Unity3d,Unity5,Pinchzoom,我正在尝试在一个基于Unity UI的应用程序中重新实现一个从收缩到缩放的系统。大约六个月前,我通过将UI画布制作成常规游戏对象的子对象,并操纵该对象的变换,将其组合在一起,但自从更新到Unity 5.5+后,我发现这不起作用。我能得到的最近距离允许收缩手势更改画布的缩放因子,这a)会使图像、面板等根据其对齐方式不正确地调整大小,b)缩放后不允许平移 到目前为止,我得到的是: public class PinchToZoomScaler : MonoBehaviour { public
public class PinchToZoomScaler : MonoBehaviour {
public Canvas canvas; // The canvas
public float zoomSpeed = 0.5f; // The rate of change of the canvas scale factor
public float _resetDuration = 3.0f;
float _durationTimer = 0.0f;
float _startScale = 0.0f;
void Start() {
_startScale = canvas.scaleFactor;
}
void Update()
{
// If there are two touches on the device...
if (Input.touchCount == 2) {
// Store both touches.
Touch touchZero = Input.GetTouch (0);
Touch touchOne = Input.GetTouch (1);
// Find the position in the previous frame of each touch.
Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;
// Find the magnitude of the vector (the distance) between the touches in each frame.
float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;
// Find the difference in the distances between each frame.
float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;
// ... change the canvas size based on the change in distance between the touches.
canvas.scaleFactor -= deltaMagnitudeDiff * zoomSpeed;
// Make sure the canvas size never drops below 0.1
canvas.scaleFactor = Mathf.Max (canvas.scaleFactor, _startScale);
canvas.scaleFactor = Mathf.Min (canvas.scaleFactor, _startScale * 3.0f);
_durationTimer = 0.0f;
} else {
_durationTimer += Time.deltaTime;
if (_durationTimer >= _resetDuration) {
canvas.scaleFactor = _startScale;
}
}
}
}
正如我所说,这在一定程度上是可行的,但它并没有给我一个很好的统一缩放,也不允许我平移画布。提前感谢您的帮助。您可以使用此函数(只需将负deltaMagnitudeDiff传递给它即可)
同样,以类似(0.05)的比率对deltaMagnitudeDiff进行多次叠加也是很好的
float currentScale=1f;
空心缩放(浮动增量)
{
电流标度+=增量;
如果(currentScale>=maxScale)
{
currentScale=maxScale;
}
else if(当前刻度最大值+偏移量)
温度x=最大值x+偏移量x;
如果(温度y<-最大值+偏移量)
温度y=-MaxY+offsetY;
否则如果(温度y>MaxY+offsetY)
温度y=最大值+偏移量;
transform.localPosition=temp;
}
只需从事件触发器组件调用函数(BeginDrag&Drag) >我用捏法缩放物体的方法是,当物体在屏幕中央时,它在任何触摸屏上工作:
if(Input.touchCount==2)
{
//检查两次触摸之间的距离,然后使用该距离缩放
//通过将两个手指进一步移动或彼此靠近来移动对象。
Touch touch0=Input.GetTouch(0);
Touch Touch 1=输入。GetTouch(1);
if(isScaling)//仅当scaling为true时才会执行此操作
{
float currentTouchDistance=getTouchDistance();
浮点deltaTouchDistance=当前触摸距离-触摸距离原点;
浮点数百分比=(deltaTouchDistance/1200f)+1f;
Vector3 scaleTemp=transform.localScale;
scaleTemp.x=比例百分比*原始比例.x;
scaleTemp.y=比例百分比*原始比例.y;
scaleTemp.z=比例百分比*原始比例.z;
//要使对象捕捉到100%,正在进行检查,以查看对象比例是否接近100%,
//如果是,则比例将恢复为100%,以便捕捉到正常比例。
//这是一种生活质量特征,因此很容易获得对象的原始大小。
如果(scaleTemp.x*100<102&&scaleTemp.x*100>98)
{
scaleTemp.x=1;
scaleTemp.y=1;
scaleTemp.z=1;
}
//在这里,我们应用上面所做的计算来实际使对象变大/变小。
transform.localScale=scaleTemp;
}
其他的
{
//如果两个手指触摸屏幕,但isScaling不正确,我们将查看
//屏幕中央正在查看对象,如果将isScalinf设置为true;
射线;
雷卡斯特·希特鲁克;
光线=cam.ViewportPointToRay(新矢量3(0.5f,0.5f,0));
if(物理.光线投射(光线,外触,100f))
{
if(hitTouch.transform==transform)
{
isScaling=true;
//确保初始接触时手指之间的距离用作原始距离
touchDistanceOrigin=getTouchDistance();
originalScale=transform.localScale;
}
}
}
}
将此脚本附加到画布对象中,以便通过挤压放大和缩小该对象
using UnityEngine;
using UnityEngine.EventSystems;
public class ObjectScalling : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private bool _isDragging;
private float _currentScale;
public float minScale, maxScale;
private float _temp = 0;
private float _scalingRate = 2;
private void Start()
{
_currentScale = transform.localScale.x;
}
public void OnPointerDown(PointerEventData eventData)
{
if (Input.touchCount == 1)
{
_isDragging = true;
}
}
public void OnPointerUp(PointerEventData eventData)
{
_isDragging = false;
}
private void Update()
{
if (_isDragging)
if (Input.touchCount == 2)
{
transform.localScale = new Vector2(_currentScale, _currentScale);
float distance = Vector3.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
if (_temp > distance)
{
if (_currentScale < minScale)
return;
_currentScale -= (Time.deltaTime) * _scalingRate;
}
else if (_temp < distance)
{
if (_currentScale > maxScale)
return;
_currentScale += (Time.deltaTime) * _scalingRate;
}
_temp = distance;
}
}
}
使用UnityEngine;
使用UnityEngine.EventSystems;
公共类ObjectScaling:MonoBehavior、IPInterDownHandler、IPInterUpHandler
{
私人厕所;
私人浮标;
公共浮点数,最大刻度;
专用浮点数_temp=0;
私有浮动_scalingRate=2;
私有void Start()
{
_currentScale=transform.localScale.x;
}
POINTERDOWN上的公共无效(PointerEventData事件数据)
{
如果(Input.touchCount==1)
{
_IsDraging=true;
}
}
POINTERUP上的公共无效(PointerEventData事件数据)
{
_IsDraging=错误;
}
私有void更新()
{
如果(_istragging)
如果(Input.touchCount==2)
{
transform.localScale=新向量2(\u currentScale,\u currentScale);
float distance=Vector3.距离(Input.GetTouch(0).位置,Input.GetTouch(1).位置);
如果(温度>距离)
{
如果(_currentScalemaxScale)
返回;
_currentScale+=(Time.deltaTime)*\u scalingRate;
}
_温度=距离;
}
}
}
提醒:此脚本仅适用于画布对象
public class Pan : MonoBehaviour
{
public float Speed;
Vector3 startDragPosition;
public void BeginDrag ()
{
startDragPosition = Input.mousePosition;
}
public void Drag ()
{
transform.localPosition += (Input.mousePosition - startDragPosition) * Speed;
startDragPosition = Input.mousePosition;
ValidatePosition ();
}
public void ValidatePosition ()
{
var temp = transform.localPosition;
var width = ((RectTransform)transform).sizeDelta.x;
var height = ((RectTransform)transform).sizeDelta.y;
var MaxX = 0.5f * width * Mathf.Max (0, transform.localScale.x - 1);
var MaxY = 0.5f * height * Mathf.Max (0, transform.localScale.y - 1);
var offsetX = transform.localScale.x * width * (((RectTransform)transform).pivot.x - 0.5f);
var offsetY = transform.localScale.y * width * (((RectTransform)transform).pivot.y - 0.5f);
if (temp.x < -MaxX + offsetX)
temp.x = -MaxX + offsetX;
else if (temp.x > MaxX + offsetX)
temp.x = MaxX + offsetX;
if (temp.y < -MaxY + offsetY)
temp.y = -MaxY + offsetY;
else if (temp.y > MaxY + offsetY)
temp.y = MaxY + offsetY;
transform.localPosition = temp;
}
using UnityEngine;
using UnityEngine.EventSystems;
public class ObjectScalling : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
private bool _isDragging;
private float _currentScale;
public float minScale, maxScale;
private float _temp = 0;
private float _scalingRate = 2;
private void Start()
{
_currentScale = transform.localScale.x;
}
public void OnPointerDown(PointerEventData eventData)
{
if (Input.touchCount == 1)
{
_isDragging = true;
}
}
public void OnPointerUp(PointerEventData eventData)
{
_isDragging = false;
}
private void Update()
{
if (_isDragging)
if (Input.touchCount == 2)
{
transform.localScale = new Vector2(_currentScale, _currentScale);
float distance = Vector3.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
if (_temp > distance)
{
if (_currentScale < minScale)
return;
_currentScale -= (Time.deltaTime) * _scalingRate;
}
else if (_temp < distance)
{
if (_currentScale > maxScale)
return;
_currentScale += (Time.deltaTime) * _scalingRate;
}
_temp = distance;
}
}
}