适用于 Android/IOS 的 Canvas 上的 Unity 平滑移动和缩放 UI
Posted
技术标签:
【中文标题】适用于 Android/IOS 的 Canvas 上的 Unity 平滑移动和缩放 UI【英文标题】:Unity Smooth Move and Zoom UI on Canvas for Android/IOS 【发布时间】:2021-06-30 21:58:59 【问题描述】:我为我的任务编写了这个脚本,在论坛上冲浪后我找不到好的决定,所以我为你们修改了代码并发布了这个。也许有人会有用。如果你有一些修改,我会很高兴听到?
【问题讨论】:
你应该在reddit或其他地方发布这个:) 【参考方案1】:using UnityEngine;
public class MovableScrollRectFree : MonoBehaviour
[Space(2)][Header("Settings")]
// Content need set Anchor Presets [Middle & Center]
[SerializeField] private GameObject Content;
[Space(10)]
[SerializeField] private float MinZoom = 0.5f;
[SerializeField] private float MaxZoom = 3f;
[SerializeField] private float ZoomSpeed = -0.002f;
[SerializeField] private float MoveSpeed = 1f;
[Space(10)]
[SerializeField] [Range(1, 10)] private int SmoothMove = 6;
[SerializeField] [Range(1, 10)] private int SmoothScale = 6;
[Space(10)]
// Can be zero values
[SerializeField] private float MinPermissibleHeightOffset;
[SerializeField] private float MaxPermissibleHeightOffset;
[SerializeField] private float MinPermissibleWidthOffset;
[SerializeField] private float MaxPermissibleWidthOffset;
private RectTransform ContentRect;
private Vector2 ContentSizeDelta;
private Vector2 TargetScale;
private Vector2 TargetPosition;
private float moveMagnitude;
private float scaleMagnitude;
private float oldMoveMagnitude;
private float oldScaleMagnitude;
private float startScaleMagnitude;
private float newScaleMagnitude;
private Vector2 ContentScaleOnStart;
private Vector2 ContentPositionOnStart;
private Vector2 startPostiton;
private Vector2 newPosition;
private Vector2 stepMove;
private Vector3 stepScale;
private int avalibleMoveSteps;
private int avalibleScaleSteps;
Vector2 fingerPosition1;
Vector2 fingerPosition2;
private bool _isPinching;
private bool active;
private void Awake()
Input.multiTouchEnabled = true;
void Start()
ContentRect = Content.GetComponent<RectTransform>();
ContentSizeDelta = ContentRect.sizeDelta;
private void Update()
if (Input.touchCount == 2)
active = true;
else if (active)
active = false;
TryOutDangerZone();
_isPinching = false;
private void FixedUpdate()
TransformContent();
if (!active) return;
if (Input.touchCount != 2) return;
fingerPosition1 = Input.touches[0].position;
fingerPosition2 = Input.touches[1].position;
if (!_isPinching)
_isPinching = true;
OnPinchStart();
OnPinch();
private void OnPinchStart()
startPostiton = GetMidlePosition(fingerPosition1, fingerPosition2);
startScaleMagnitude = (fingerPosition1 - fingerPosition2).magnitude;
ContentScaleOnStart = ContentRect.localScale;
ContentPositionOnStart = ContentRect.anchoredPosition;
private void OnPinch()
newPosition = GetMidlePosition(fingerPosition1, fingerPosition2);
oldMoveMagnitude = moveMagnitude;
oldScaleMagnitude = scaleMagnitude;
moveMagnitude = (newPosition - startPostiton).magnitude;
newScaleMagnitude = (fingerPosition1 - fingerPosition2).magnitude;
scaleMagnitude = startScaleMagnitude - newScaleMagnitude;
if (Mathf.Abs(scaleMagnitude - oldScaleMagnitude) > 1 ||
Mathf.Abs(moveMagnitude - oldMoveMagnitude) > 1)
CalculateScaleContent();
CalculateMoveContent();
private void TransformContent()
if (avalibleScaleSteps > 0)
ContentRect.localScale += stepScale * (avalibleScaleSteps / 2f);
avalibleScaleSteps--;
if (avalibleMoveSteps > 0)
ContentRect.anchoredPosition += stepMove * (avalibleMoveSteps / 2f);
avalibleMoveSteps--;
private void CalculateScaleContent()
float tempScale = Mathf.Clamp(ContentScaleOnStart.x + (scaleMagnitude * ZoomSpeed), MinZoom, MaxZoom);
TargetScale = new Vector2(tempScale, tempScale);
stepScale = (TargetScale - (Vector2)ContentRect.localScale) / SmoothScale;
avalibleScaleSteps = SmoothScale;
private void CalculateMoveContent()
Vector2 localScale = ContentRect.localScale;
float maxMoveOffsetX = Mathf.Abs((ContentSizeDelta.x * localScale.x) - ContentSizeDelta.x) / 2 + MaxPermissibleWidthOffset;
float maxMoveOffsetY = Mathf.Abs((ContentSizeDelta.y * localScale.y) - ContentSizeDelta.y) / 2 + MaxPermissibleHeightOffset;
float offcetMoveX = newPosition.x - startPostiton.x;
float offcetMoveY = newPosition.y - startPostiton.y;
TargetPosition = new Vector2(
Mathf.Clamp(ContentPositionOnStart.x + (offcetMoveX * MoveSpeed), -maxMoveOffsetX, maxMoveOffsetX),
Mathf.Clamp(ContentPositionOnStart.y + (offcetMoveY * MoveSpeed), -maxMoveOffsetY, maxMoveOffsetY));
stepMove = (TargetPosition - ContentRect.anchoredPosition) / SmoothMove;
avalibleMoveSteps = SmoothMove;
private void TryOutDangerZone()
Vector2 localScale = ContentRect.localScale;
float maxMoveOffsetX = Mathf.Abs((ContentSizeDelta.x * localScale.x) - ContentSizeDelta.x) / 2 + MinPermissibleWidthOffset;
float maxMoveOffsetY = Mathf.Abs((ContentSizeDelta.y * localScale.y) - ContentSizeDelta.y) / 2 + MinPermissibleHeightOffset;
TargetPosition = new Vector2(
Mathf.Clamp(TargetPosition.x, -maxMoveOffsetX, maxMoveOffsetX),
Mathf.Clamp(TargetPosition.y, -maxMoveOffsetY, maxMoveOffsetY));
stepMove = (TargetPosition - ContentRect.anchoredPosition) / SmoothMove;
avalibleMoveSteps = SmoothMove;
private Vector2 GetMidlePosition(Vector2 pos1, Vector2 pos2)
return Vector2.Lerp(pos1, pos2, 0.5f);
【讨论】:
以上是关于适用于 Android/IOS 的 Canvas 上的 Unity 平滑移动和缩放 UI的主要内容,如果未能解决你的问题,请参考以下文章
适用于 android、ios 和 blackberry 的 Codenameone 应用内计费
通过 PhoneGap 中的短信分享手机地理位置坐标(适用于 Android/IOS)
适用于 Android、iOS 和 PC 的通用跨平台应用程序 - 理论上 [关闭]
带有一个适用于android、ios、web的插件的flutter firebase(实时)数据库? [复制]