How would I go about tinting multiple targets with a single click? For example if I have an Image (background) with a button component attached to it, and as a child of this image I have another image which displays an icon for the button. When I click on the button only the background will tint its color, not the icon.
Is there a way I can achieve this effect? I know this is not NGUI, but for reference I could add multiple button components to a single GameObject in NGUI and change the targets to achieve the effect.
I would just create a new type of button that inherits from button, and Override DoStateTransition, then you can find all images in the parent or something, and loop through each of them on the transition
something like this
protected virtual IEnumerator TweenColorFromCurrent (Color ToColor, float duration)
{
for (float f = 0; f <= duration; f = f + Time.deltaTime) {
obUI.ForEach(x=>x.material.color = Color.Lerp (x.material.color, ToColor, f));
yield return null;
}
obUI.ForEach(x=>x.material.color = ToColor);
}
protected override void DoStateTransition (Selectable.SelectionState state, bool instant)
{
obUI = this.GetComponentsInChildren<Renderer>().ToList();
Debug.Log ("inside state transition");
if (state == SelectionState.Pressed) {
StopAllCoroutines ();
StartCoroutine (TweenColorFromCurrent (this.colors.pressedColor, this.colors.fadeDuration));
}
if (state == Selectable.SelectionState.Highlighted) {
Debug.Log ("state was highlight");
//StopAllCoroutines();
StartCoroutine (TweenColorFromCurrent (this.colors.highlightedColor, this.colors.fadeDuration));
}
if (state == Selectable.SelectionState.Normal) {
Debug.Log ("state was normal");
StopAllCoroutines ();
StartCoroutine (TweenColorFromCurrent (this.colors.normalColor, this.colors.fadeDuration));
}
}
}
}
Thanks for the help! I did not know that the UI had gone open source already, I knew they was planning to but didnt see that post! Ill be checking it out for sure, thanks again!
I know this is an old Post but since google directed me here, probably others will come here aswell.
I found a simple solution the the scenario miminito describes.
Create a Button and add your own button sprite as Source Image.
Create another Button and use your background sprite (in my case a glowing outline) as Source Image for this one.
Put the background as child of the first button
Both Buttons will detect if the mouse is hovering over it or if they are clicked.
Nonetheless when you are assigning your script to the “On Click ()” function:
Put it on the last child in the hirachy
I’m not exactly sure why it can’t be on the parent, but somehow it then gets blocked by the child.
Guess the last child is on top of the others, even if they all have the same coords.
In case your button keeps highlighted after you clicked it:
Using [SerializeField] Graphic[] _sourceImages; works, you just have to activate the inspector debug view to access the field (top right of the inspector panel, click on the three dot and check debug). You also can create a custom editor for this class to handle it without having to switch from normal to debug mode.
There is an Animation transition type which allows to animate any objects for different states of the button (or any other control which supports transitions)
For anyone still interested, I reworked it so it’s a tad bit more user friendly inspector wise:
This is the MultiImageButton.cs
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(MultiImageTargetGraphics))]
public class MultiImageButton : Button
{
private Image[] targetImages;
private MultiImageTargetGraphics targetGraphics;
protected override void Start()
{
targetGraphics = GetComponent<MultiImageTargetGraphics>();
targetImages = targetGraphics.GetTargetImages;
base.Start();
}
protected override void DoStateTransition(SelectionState state, bool instant)
{
if (!targetGraphics) return;
var targetColor =
state == SelectionState.Disabled ? colors.disabledColor :
state == SelectionState.Highlighted ? colors.highlightedColor :
state == SelectionState.Normal ? colors.normalColor :
state == SelectionState.Pressed ? colors.pressedColor :
state == SelectionState.Selected ? colors.selectedColor : Color.white;
foreach (var image in targetImages)
image.CrossFadeColor(targetColor, instant ? 0 : colors.fadeDuration, true, true);
}
}
Accompanied by MultiImageTargetGraphics
using UnityEngine;
using UnityEngine.UI;
public class MultiImageTargetGraphics : MonoBehaviour
{
[SerializeField] private Image[] targetImages;
public Image[] GetTargetImages => targetImages;
}
All you do is add MultiImageButton, replacing the standard button, and just add the target images on the MultiImageTargetGraphics that will be added with it. TargetGraphic of MultiImageButton is unused.
@the1whom0x
I have rewritten your code a little bit, so that it works for all kinds of graphics and not only images.
This is the MultiImageButton.cs
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(MultiImageTargetGraphics))]
public class MultiImageButton : Button
{
private Graphic[] graphics;
private MultiImageTargetGraphics targetGraphics;
protected override void Start()
{
base.Start();
}
protected override void DoStateTransition(SelectionState state, bool instant)
{
//get the graphics, if it could not get the graphics, return here
if (!GetGraphics())
return;
var targetColor =
state == SelectionState.Disabled ? colors.disabledColor :
state == SelectionState.Highlighted ? colors.highlightedColor :
state == SelectionState.Normal ? colors.normalColor :
state == SelectionState.Pressed ? colors.pressedColor :
state == SelectionState.Selected ? colors.selectedColor : Color.white;
foreach (var graphic in graphics)
graphic.CrossFadeColor(targetColor, instant ? 0 : colors.fadeDuration, true, true);
}
private bool GetGraphics()
{
if(!targetGraphics) targetGraphics = GetComponent<MultiImageTargetGraphics>();
graphics = targetGraphics?.GetTargetGraphics;
return graphics != null && graphics.Length > 0;
}
}
This is the MultiImageTargetGraphics.cs
using UnityEngine;
using UnityEngine.UI;
public class MultiImageTargetGraphics : MonoBehaviour
{
[SerializeField] private Graphic[] targetGraphics;
public Graphic[] GetTargetGraphics => targetGraphics;
}