Skip to main content
added code from comments
Source Link
user3797758
  • 3.7k
  • 2
  • 31
  • 53

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;
        }
    }
}
```

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;
        }
    }
}
```
Source Link

How do I write a script for Unity that allows a gameobject to be scaled using pinch & zoom touch controls?

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.