I have two buttons. They both have a specific action. But when both are pressed together, I want to perform a completely different action. I dont understand how I can achieve this
you can make a button play an animation (button animation or character animation, it doesn’t matter). and pressing another button will play another animation. but you can have it where you can press one button to start one animation and then while inside that animation you press other button to get a completely different animation.
A fantastic example is Mario 64.
- Pressing the jump button normally causes Mario to jump (with a jump animation).
- Pressing crouch button causes Mario to crouch (again with said animation)
- Press jump while crouched and Mario will perform a back-flip.
- If you have Mario run and then crouch he’ll play an animation of him in crouch stance and sliding and kicking up dust, pressing jump during this animation causes Mario to perform a long jump.
- Run forward, quickly reverse direction and Mario plays this skidding animation. Pressing jump during this animation and Mario performs his jump side-flip animation.
Mapping button actions based on animations has its benefits. First off it provides the player instant feedback on the first press even when desired action hasn’t actually happened yet. It also provides an easily apparent input window for the user so that they aren’t forced to input the button on the exact frame (which in practice will be pretty tough). And finally it also (in a very intuitive way) informs the player the time-frame in which they can perform the special action.
From a design standpoint you can easily tweak the animation durations to adjust the time-frame for the special actions. and coding-wise you can use Mecanim and StateMachineBehaviours to control which animation states they should go to based on inputs, default transitioning to an idle animation if nothing is pressed.
I dont think you understood my question, I want nothing to do with animation. All of the code is already made, all I want to know is how to detect if both buttons are touched at the same time and thus they dont execute their specific code but another method.
Simple enough. You need code to detect if one button is down. This can be done by setting a bool in IPointerDown. Then you will need to detect if the button is no longer down. This will need to be done in IPointerUp and IPointerExitHandler. Do this for both buttons.
Then in Update you will need to check which buttons are down, and call the appropriate code.
Whats the difference between IPointerUp and IPointerExitHandler?
I understood your question to the extent of what you’ve provided. There’s a number of ways you can handle and i went through them all in my head.
Are the buttons overlapping? You said UI Buttons so the only way I can see you being able to press both at the same time is either the buttons overlap and your pointer can press both, or theres a time window in which you have to press both, or you’re using multiple pointers.
Overlapping buttons doesn’t quite make sense… just make a third new button and attach the new action there. Though you could write up your own unique raycaster and input module so that you can press both, a third button is far easier and cleaner to implement.
What do you mean exactly by “pressed together”? (on the exact frame or within a certain time window). Relying on the user to press a button at the exact frame of an event, even to an another button they pressed is unreliable. Many timing games (mostly music games like DDR and Guitar Hero) purposefully holds onto the input for at least a couple frames for this very reason.
Thus in the end resorting to a State Machine seemed like the best course. The buttons don’t hold the action themselves. they simply relay that they’ve been pressed to a State Machine. The action to be performed is managed by the state machine when its enters an action state. A button press would cause you to enter a timing state and then a timeout or another button press would cause you to exit that state and enter an action state. By timing out you’d enter one action state to perform one action, but by pressing a specific button you’d enter another action state which performs the special action. the timeout duration can be long like 3 seconds or short like 0-2 frames.
only thing left is to detect when a UI button is pressed (not clicked)
public class PressedButton : UnityEngine.UI.Button
{
[System.Serializable]
public class PointerEventDataEvent : UnityEngine.Events.UnityEvent<PointerEventData>{}
public PointerEventDataEvent OnButtonPressed;
public PointerEventDataEvent OnButtonReleased;
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
if(eventData.button != PointerEventData.InputButton.Left) return;
if(!base.IsInteractable()) return;
if(!base.IsActive()) return;
OnButtonPressed.Invoke(eventData);
}
public override void OnPointerUp(PointerEventData eventData)
{
if(IsPressed() && eventData.button == PointerEventData.InputButton.Left)
{
OnButtonReleased.Invoke(eventData);
}
base.OnPointerUp(eventData);
}
public override void OnPointerExit(PointerEventData eventData)
{
if(IsPressed())
{
OnButtonReleased.Invoke(eventData);
}
base.OnPointerExit(eventData);
}
//expose protected method as public
public new bool IsPressed()
{
return base.IsPressed();
}
}
onPointerExit is when you hover the pointer away from the button.
OnPointerUp is when you release the pointer when over the button.
when you OnPointerDown on a button and then OnPointerUp on that same button its considered a click. when you onPointerDown and then OnPointerExit (and then release while not hovering over the button) thats considered a cancel and you have not clicked the button.
Thank you for the clarification. Im using touch controls thats why I meant both buttons being pressed at the same time. I apologize for the misunderstanding.