I need a script for Unity that allows a gameobject to be scaled using pinch & zoom touch controls. I have found lots of answers for scripts that cause the camera to zoom in/out but I want a gameobject to scale up/down instead.
I'm using the following code
using UnityEngine;
using UnityEngine.EventSystems;
namespace Development
{
/// <summary>
/// Zoom component which will handle the scroll wheel events and zooms in on the pointer
/// </summary>
public class ZoomComponent : MonoBehaviour, IScrollHandler
{
/// <summary>
/// The Target RectTransform the scale will be applied on.
/// </summary>
[SerializeField]
private RectTransform Target;
/// <summary>
/// The minimum scale of the RectTransform Target
/// </summary>
[SerializeField]
private float MinimumScale = 0.5f;
/// <summary>
/// The maximum scale of the RectTransform Target
/// </summary>
[SerializeField]
private float MaximumScale = 3f;
/// <summary>
/// The scale value it should increase / decrease based on mouse wheel event
/// </summary>
[SerializeField]
private float ScaleStep = 0.25f;
// Used camera for the local point calculation
[SerializeField]
private new Camera camera = null;
private Camera Camera
{
get
{
if (camera == null) return camera = Target.GetComponentInParent<Canvas>().worldCamera;
return camera;
}
}
/// <summary>
/// Current scale which is used to keep track whether it is within boundaries
/// </summary>
private float scale = 1f;
private void Awake()
{
if (Target == null) Target = (RectTransform) transform;
// Get the current scale
var targetScale = Target.localScale;
if(!targetScale.x.Equals(targetScale.y)) Debug.LogWarning("Scale is not uniform.");
scale = targetScale.x;
// Do a check for the anchors of the target
if(Target.anchorMin != new Vector2(0.5f, 0.5f) || Target.anchorMax != new Vector2(0.5f, 0.5f)) Debug.LogWarning("Anchors are not set to Middle(center)");
}
public void OnScroll(PointerEventData eventData)
{
// Set the new scale
var scrollDeltaY = (eventData.scrollDelta.y * ScaleStep);
var newScaleValue = scale + scrollDeltaY;
ApplyScale(newScaleValue, eventData.position);
}
/// <summary>
/// Applies the scale with the mouse pointer in mind
/// </summary>
/// <param name="newScaleValue"></param>
/// <param name="position"></param>
private void ApplyScale(float newScaleValue, Vector2 position)
{
var newScale = Mathf.Clamp(newScaleValue, MinimumScale, MaximumScale);
// If the scale did not change, don't do anything
if (newScale.Equals(scale)) return;
// Calculate the local point in the rectangle using the event position
RectTransformUtility.ScreenPointToLocalPointInRectangle(Target, position, Camera, out var localPointInRect);
// Set the pivot based on the local point in the rectangle
SetPivot(Target, localPointInRect);
// Set the new scale
scale = newScale;
// Apply the new scale
Target.localScale = new Vector3(scale, scale, scale);
}
/// <summary>
/// Sets the pivot based on the local point of the rectangle <see cref="RectTransformUtility.ScreenPointToLocalPointInRectangle"/>.
/// Keeps the RectTransform in place when changing the pivot by countering the position change when the pivot is set.
/// </summary>
/// <param name="rectTransform">The target RectTransform</param>
/// <param name="localPoint">The local point of the target RectTransform</param>
private void SetPivot(RectTransform rectTransform, Vector2 localPoint)
{
// Calculate the pivot by normalizing the values
var targetRect = rectTransform.rect;
var pivotX = (float) ((localPoint.x - (double) targetRect.x) / (targetRect.xMax - (double) targetRect.x));
var pivotY = (float) ((localPoint.y - (double) targetRect.y) / (targetRect.yMax - (double) targetRect.y));
var newPivot = new Vector2(pivotX, pivotY);
// Delta pivot = (current - new) * scale
var deltaPivot = (rectTransform.pivot - newPivot) * scale;
// The delta position to add after pivot change is the inversion of the delta pivot change * size of the rect * current scale of the rect
var rectSize = targetRect.size;
var deltaPosition = new Vector3(deltaPivot.x * rectSize.x, deltaPivot.y * rectSize.y) * -1f;
// Set the pivot
rectTransform.pivot = newPivot;
rectTransform.localPosition += deltaPosition;
}
}
}
```
camera.orthographicSize
orcamera.fieldOfView
orcamera.transform.position
with a corresponding change togameObject.transform.localScale
instead? Show us how you've attempted to solve this problem and where you still need help. \$\endgroup\$newScaleValue
in this script. Take the center point of the touches involved in the pinch, and use that as theposition
. That should give you everything you need to adapt this script to work with touch. How have you tried to make this adaptation so far? \$\endgroup\$