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.orthographicSizeorcamera.fieldOfVieworcamera.transform.positionwith a corresponding change togameObject.transform.localScaleinstead? Show us how you've attempted to solve this problem and where you still need help. \$\endgroup\$newScaleValuein 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\$