0
\$\begingroup\$

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;
        }
    }
}
```
\$\endgroup\$
4
  • \$\begingroup\$ Presumably you considered taking one of these scripts you found, and replacing modifications to camera.orthographicSize or camera.fieldOfView or camera.transform.position with a corresponding change to gameObject.transform.localScale instead? Show us how you've attempted to solve this problem and where you still need help. \$\endgroup\$
    – DMGregory
    Nov 18, 2021 at 23:24
  • \$\begingroup\$ I've been using this script below to achieve the same effect using the mouse scroll but I can't figure out how to make it work for touch controls. Thanks for the quick reply! link to code couldn't paste whole code sorry \$\endgroup\$
    – Hzata
    Nov 19, 2021 at 11:06
  • \$\begingroup\$ just updating the link because unity answers is hiding it forum.unity.com/threads/… \$\endgroup\$
    – Hzata
    Nov 19, 2021 at 12:00
  • \$\begingroup\$ It looks like you should be able to hybridize this with one of the scripts you found for pinch-zoom. Take the zoom amount calculated in the pinch-zoom script, and use it to make your newScaleValue in this script. Take the center point of the touches involved in the pinch, and use that as the position. 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\$
    – DMGregory
    Nov 19, 2021 at 14:41

0

You must log in to answer this question.

Browse other questions tagged .