- Home /
UGUI UI, How to increase Hitzone, Click area, Button Rect, respectivlly to the Image component?
What is the fastest most accurate (platform independent) way to do that?
My personal thoughts - (I could just edit the image with more dead space around it, but thats a very bad solution. I could create a separate button without a zero alpha and a big hitzone, and just place an image underneath it, However then the transition effects that we get from the Button component can't be used. Maybe there is a way that a click on one button will activate a click on another button?).
I have no better solution for you, but, given how pervasive Unity is on mobile devices, I am sad that the uGUI buttons don't simply have a way of defining a bigger touch area than the visual button.
Answer by Eliot_L · May 04, 2015 at 11:25 PM
I've found a solution for an invisible button that doesn't add unnecessary alpha to the scene. First, add this script to your project:
//EmptyGraphic.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class EmptyGraphic : Graphic {
protected override void OnFillVBO(List<UIVertex> vbo)
{
}
}
Then make a new button, delete the Image component, and add the EmptyGraphic component. Then hook up the Button's Target Graphic as described by Helical. Works like a charm!
Shout out to @ragzouken who gave me this tip.
I was also having trouble making adaptive layouts, but I found a solution to that too by making the invisible button a sibling of the visible button instead of a parent. Make sure it's beneath the visible button in the hierarchy, otherwise the visible button will eat clicks where it overlaps.
some other comment updated for Unity 5.2
//EmptyGraphic.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class EmptyGraphic : Graphic {
protected override void OnPopulate$$anonymous$$esh($$anonymous$$esh m)
{
m.Clear(false);
}
}
for Unity 5.3:
using UnityEngine;
using UnityEngine.UI;
public class EmptyGraphic : UnityEngine.UI.Graphic
{
protected override void OnPopulate$$anonymous$$esh(VertexHelper vh)
{
vh.Clear();
}
}
edit: Works perfectly, saves you some valuable draw calls !
Answer by gselfish · Jun 02, 2015 at 10:51 AM
Just figured this out today, apparently the best way to increase the collision area of a button is to add a UI Text element as a child.
Unlike UI Image, Text can be left blank and freely resized, creating an invisible collider box without any alpha overhead.
This seems to be the best method for me! I currently have button image as a child, and an empty text element attached to the button. Works exactly as desired without any extra scripts!
This is the most elegant and easy to implement solution. Please change best answer to this one.
Turned this into a script for convenience:
using UnityEngine;
using UnityEngine.UI;
public class LargeButton : $$anonymous$$onoBehaviour {
public int extraPixels;
public Text expansion;
// Use this for initialization
public void Expand () {
if (!expansion)
{
GameObject temp = new GameObject("Expansion");
temp.Reparent(transform, true);
expansion = temp.AddComponent<Text>();
}
expansion.text = "";
RectTransform rT = expansion.GetComponent<RectTransform>();
rT.anchor$$anonymous$$in = Vector2.zero;
rT.anchor$$anonymous$$ax = Vector2.one;
rT.sizeDelta = Vector2.one * extraPixels;
}
}
even in 2018, this is still the easiest and probably the best solution. I will say that if you're using your button as a way to fire your weapon and want to have limited "ammo" or "projectiles" in your inventory, you must turn off your "raycast target" via code, otherwise once your inventory hits "0" it'll go into the negative number and still fire. hitbox.GetComponent ().raycastTarget = false; something like this in the update will turn it off if inventory hits "0".
Answer by booferei · Sep 14, 2017 at 07:56 PM
Combing all the best from the answers before me, here's an easy fix-em-all solution. Just drop this script on a button - no need to change your layout.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ButtonHitZone : MonoBehaviour {
public float width;
public float height;
public class EmptyGraphic : Graphic {
protected override void OnPopulateMesh(VertexHelper vh) {
vh.Clear();
}
}
void OnValidate() {
RectTransform rectTransform = GetComponent<RectTransform>();
if (rectTransform != null) {
width = Mathf.Max(width, rectTransform.sizeDelta.x);
height = Mathf.Max(height, rectTransform.sizeDelta.y);
}
}
void Awake() {
createHitZone();
}
void createHitZone() {
// create child object
GameObject gobj = new GameObject("Button Hit Zone");
RectTransform hitzoneRectTransform = gobj.AddComponent<RectTransform>();
hitzoneRectTransform.SetParent(transform);
hitzoneRectTransform.localPosition = Vector3.zero;
hitzoneRectTransform.localScale = Vector3.one;
hitzoneRectTransform.sizeDelta = new Vector2(width, height);
// create transparent graphic
// Image image = gobj.AddComponent<Image>();
// image.color = new Color(0, 0, 0, 0);
gobj.AddComponent<EmptyGraphic>();
// delegate events
EventTrigger eventTrigger = gobj.AddComponent<EventTrigger>();
// pointer up
addEventTriggerListener(eventTrigger, EventTriggerType.PointerDown,
(BaseEventData data) => { ExecuteEvents.Execute(gameObject, data,
ExecuteEvents.pointerDownHandler); });
// pointer down
addEventTriggerListener(eventTrigger, EventTriggerType.PointerUp,
(BaseEventData data) => { ExecuteEvents.Execute(gameObject, data,
ExecuteEvents.pointerUpHandler); });
// pointer click
addEventTriggerListener(eventTrigger, EventTriggerType.PointerClick,
(BaseEventData data) => { ExecuteEvents.Execute(gameObject, data,
ExecuteEvents.pointerClickHandler); });
}
static void addEventTriggerListener(EventTrigger trigger, EventTriggerType eventType,
System.Action<BaseEventData> method) {
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = eventType;
entry.callback = new EventTrigger.TriggerEvent();
entry.callback.AddListener(new UnityEngine.Events.UnityAction<BaseEventData>(method));
trigger.triggers.Add(entry);
}
}
I've added some Gizmo drawing to this script for better usability. Unfortunately it exceeds the character limit of a reply so it's on pastebin. Hope this can help someone.
Just dropping by to say thank you and nice work to @booferei and @Grinning-Pickle !
Also, looks like you need to add the following to CreateHitZone(): //add canvasRenderer gobj.AddComponent();
Answer by Helical · Dec 01, 2014 at 05:48 PM
I have found What I was looking for, but maybe there is a better way out there. Here is the procedure and where the cat kicks the bucket.
Create a Button UI element somewhere and set the alpha of the Image component of the Button element to zero, resize the element to the size of the desired Hitbox( If you remove the Image component from the Button Element then it will use the Hitbox of the sub Image that we are going to add).
next create an Image Element underneath (a child in the transform hierarchy) the Button Element. And set it to the desired size of the visual image.
and lastly attach the child image as the Target Graphic in the parent Button Component.
The trick here is to have an Image component on both the Button UI element, and its child Image, and set the Target Graphic on the Button to the child image.
Its still feels like a little lengthy procedure, I hope the uGUI $$anonymous$$m will do this by default ins$$anonymous$$d of giving us a text as a child by default (which I always erase)
Beautiful! Been looking for something like this for ages now and its been right in my face the whole time lol. Gj.
They should allow to modify the clickable area freely. $$anonymous$$aybe a new component that overrides the default area could be a good solution.
I totally agree with elhispano. Basically, every mobile project I've worked on had needed this functionality somewhere.
Answer by Meceka · Jan 28, 2015 at 03:31 PM
I am just creating a new UI image, making it child of the UI element that I wish to set hitbox, set new image's alpha as 0, and that image works as a hitbox.
Edit: Use an empty UI Text as child instead. My (old) solution causes unnecessary overdraw.
Your answer
Follow this Question
Related Questions
Simulate Button presses through code unity 4.6 GUI 4 Answers
Adding child to Canvas 1 Answer
uGUI UI Button onclick static methods 3 Answers