Trying to animate my buttons when pushed (scale it down).
I used the Animation Transition on the button and in the “Pressed” clip I set my button scale to 0.8.
The problem is that if I am on the edge of my button, the states constantly switch between “Pressed” and “Highlighted” as seen in this GIF:
If I remove the “Highlighted” state, then the button gets stuck in “Pressed” state.
Another issue is that in the GIF above, the button doesn’t actually get pressed/executed, because the cursor is not inside it on mouseUp.
Am I doing this wrong or does someone have any idea of how to fix this?
EDIT: even if I don’t use any button transition and manually play animations through a script, the cursor not being inside the button on mouseUp is still an issue.
You can make the main button image invisible (set Color > Alpha to zero) and animate a child image. Unity UI will do its raycasts against the main button image, which remains the same size.
I worked around this problem by creating a script that I assign to a child object. It’s not the prettiest solution but it’s easy to implement for multiple buttons at least.
Create a child gameobject of the button (it must be a direct child)
Add this script to the gameobject:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Image))]
[RequireComponent(typeof(RectTransform))]
public class ButtonHitbox : MonoBehaviour
{
private Image _image;
private RectTransform _rt;
private RectTransform _parent;
private Vector3 _orgScale;
void Reset()
{
// Make it invisible when component is added
_image = GetComponent<Image>();
_image.color = new Color(0, 0, 0, 0);
// Reset the local position just in case
GetComponent<RectTransform>().localPosition = Vector3.zero;
}
void Awake ()
{
_rt = GetComponent<RectTransform>();
_parent = _rt.transform.parent.GetComponent<RectTransform>();
// Set transform size to same as parent
_rt.sizeDelta = _parent.sizeDelta;
_orgScale = _parent.localScale;
}
void LateUpdate ()
{
// Always use parent scale to counter the scale - do it in lateupdate after the animation has been performed
_rt.localScale = new Vector3(_orgScale.x / _parent.localScale.x, _orgScale.y / _parent.localScale.y, 1);
}
}
That should do the trick. Basically it adds a transparent child image of equal size to the parent and it compensates for any animation resizing in LateUpdate so raycasting still hits the original area. Haven’t tested it fully yet but it seems to do the trick.