Area2D only becomes invisible when clicked on the edges. (c#) - c#

I have created a pause screen Area2D for my game, in any case the player goes AFK. I wrote a code so whenever the key P is pressed it appears and everything pauses, and if it is clicked it disappears and everything goes back to normal. I wrote a code, but it didn't work
I tried this:
public override void _PhysicsProcess(float delta)
{
// Makes the pause screen visible when P is pressed
if (Input.IsActionPressed("Pause"))
{
Visible = true;
}
}
public override void _Ready()
{
}
public void _on_PauseScreen_mouse_entered()
{
if (Input.IsActionPressed("click"))
{
Visible = false;
}
}
But it only works when clicked on the edges, I know that's how collisions are but how do I make it so when anywhere the sprite is pressed, it disappears?

The problem in your code should be, that you are just checking if the action is pressed, when the mouse entered the area.
If you move the mouse to the middle of the area and click then, your event was already fired.
Create a variable to track, if the mouse is currently in the area by using entered and exit signals and use that to determine if something should happen when you click:
bool bMouseEntered = false
public override void _PhysicsProcess(float delta)
{
// Makes the pause screen visible when P is pressed
if (Input.IsActionPressed("Pause"))
{
Visible = true;
}
if (Input.IsActionPressed("click") && bMouseEntered)
{
Visible = false;
}
}
public override void _Ready()
{
}
public void _on_PauseScreen_mouse_entered()
{
bMouseEntered = true;
}
public void _on_PauseScreen_mouse_exited()
{
bMouseEntered = false;
}

I want it so if it is pressed anywhere on the pause screen, it dissapears.
That is probably the simplest case. And the easier way to do it is to put the check in _physics_process, where the other check is:
public override void _PhysicsProcess(float delta)
{
// Makes the pause screen visible when P is pressed
if (Input.IsActionPressed("Pause"))
{
Visible = true;
}
if (Input.IsActionPressed("click"))
{
Visible = false;
}
}
So it has nothing to do with collision or the mouse. It is just checking for the action regardless of where or how it happens.
We can argue that using _input or _unhandled_input is better, in particular if timing is critical, but I don't expect it to be an issue in this case.
Addendum:
I want it so when it is pressed anywhere ON THE PAUSE SCREEN. it disappears. it doesn't cover the full screen.
At the time of writing Bugfish already has a working solution. I'll give you an alternative.
Since you are using an Area2D it must have the property input_pickable, when it is set to true (which is the default) it allows to "pick" the Area2D with the mouse. And you would get this interaction in the input_event signal or overwriting _input_event. Which would look like this:
void _InputEvent(Viewport viewport, InputEvent ev, int shapeIdx)
{
var btn = ev as InputEventMouseButton;
if(btn != null && ev.ButtonIndex == ButtonList.Left && ev.Pressed)
{
Visible = false;
}
}

Related

Detect When Key Lifted - New Unity Input System

I am currently working on a platform video game with Unity and am not sure how to detect when a key is lifted using the new input system.
I would like to know, if possible, can you detect when the key is lifted and assign the value to a bool, using my current settings.
So far, I have this code:
public void Jump(InputAction.CallbackContext context)
{
if (context.performed)
{
jump = true;
wasJumpLifted = true;
}
if (context.canceled)
{
wasJumpLifted = false;
}
else
{
wasJumpLifted = true;
}
}
The problem with this code is that it will only set wasJumpLifted to true if you press down the jump key again, as the entire function will not be invoked without me pressing the jump key.
Here's the solution
public bool isPressed;
public void Jump(InputAction.CallbackContext context)
{
// To keep the state in a boolean.
isPressed = (!context.started || context.performed) ^ context.canceled;
// When the key is pressed down.
if (context.started && !context.performed)
Debug.Log("Pressed Down");
// When the key is lifted up.
if (context.canceled && !context.performed)
Debug.Log("Lifted Up");
}
In my projects I use the one-liner:
public void Jump(InputAction.CallbackContext context) => isPressed = (!context.started || context.performed) ^ context.canceled;
This can be hard to read, but when do you need to read the code to handle these actions?

Unity - Input.GetMouseButtonDown

I created a script where by clicking on the smartphone display, an object was activated. I used Input.GetMouseButtonDown(0) to check if a tap was made on the display. The script works fine, but I have a problem: if I insert a button in the scene, clicking on the button I receive both the click of the button and that of the Input.GetMouseButtonDown function. How could I "divide" the two touches?
// Example
void Update()
{
if (Input.GetMouseButtonDown(0))
myObject.SetActive(true);
}
public void PauseButton()
{
// Open Pause Panel
}
I was thinking of deleting "Input.GetMouseButtonDown (0)" and using an invisible button and resizing it on the portion of the display I needed.
Add Tag to your UI button like: "UI"
Below function tells whether a click was Over a UI object tagged with a UI tag, so you can check in your screen tap function if you should fire your event or not
public static class InputHandler
{
public const string CompareTagForUIElements = "UI";
public static bool IsPointerOverUIObject(int touchId)
{
var eventDataCurrentPosition = new PointerEventData(EventSystem.current);
// I'm using touch since you are talking about smartphones,
// if you still need click use Input.mousePosition
eventDataCurrentPosition.position = new Vector2(GetTouch(touchId).position.x, GetTouch(touchId).position.y);
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
for (int i = 0; i < results.Count; i++)
{
if (results[i].gameObject.CompareTag(CompareTagForUIElements))
return true;
}
return false;
}
}
So rather than
public void ITappedOnScreen()
{
if(Input.GetMouseButtonDown(0))
Debug.Log("Screen tapped");
}
use
public void ITappedOnScreen()
{
if(Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Begin &&
!InputHandler.IsPointerOverUIObject(0))
Debug.Log("Screen tapped");
}

UNITY - Make a gameobject inactive and active

I have game objects which is button (Called as tiles), when the button is clicked it will be inactive and there's a condition to be tested if the condition is true the button will be destroyed but if its false the button will back to its active status.
My game Manager script (The condition):
public void checkword()
{
wordBuilded = displayer.text.ToString();
if (txtContents.Contains(wordBuilded))
{
Debug.Log(wordBuilded + " Is on the list");
wordScore++;
Debug.Log(wordScore);
}
else
{
Debug.Log("Someting is wrong..");
FindObjectOfType<LetterTiles>().tileStatus();
}
}
On my Button (Tile) script (Script attached to the buttons):
public void letterClick()
{
gameManager.currentWord += letter;
gameObject.SetActive(false);
}
public void tileStatus()
{
gameObject.SetActive(true);
}
When an object is deactivated Unity won't find it using FindObjectOfType.
either keep a local reference to the object [the button] in the game manager before you disable it or hide the button in a different way.
Since you are using a Button, you can use the interactable property of the button to make it disabled [and if you want it to be hidden then change the disabled color to transparent] like:
gameobject.GetComponent<Button>().interactable = false;

SharpDx in Unity3D - Buttons does not work anymore when click other window of editor

As you most probably know, Unity3D have terrible buil-in input system what is unable to change configuration runtime so i decised to write own input system based on SharpDX DirectInput. I know well directInput is not officialy recomendet but i like it for its ability to work with device of all kinds (Like Trust dual stick gamepad GTX 28 of mine. Originaly purchased for PSX emulation).
I using class below to representate button object
public class InputButton
{
public JoystickOffset button;
public Key key;
public int pressValue;
public int relaseValue;
public bool isJoystick;
public InputButton(JoystickOffset button, int pressValue, int relaseValue)
{
this.button = button;
this.pressValue = pressValue;
this.relaseValue = relaseValue;
isJoystick = true;
}
public InputButton(Key key, int pressValue, int relaseValue)
{
this.key = key;
this.pressValue = pressValue;
this.relaseValue = relaseValue;
isJoystick = false;
}
}
Then i replace Unity's (pretty terrible method by the way) Input.GetKeyDown with my own (If you name class same as one of unity's classes you replace it. I know someone must not like use of static here but i see it very benefical)
public static bool GetKeyDown(InputButton button)
{
bool pressed = false;
keyboard.Poll();
keyboardData = keyboard.GetBufferedData();
if (button.isJoystick == false)
{
foreach (var state in keyboardData)
{
if (state.Key == button.key && state.Value == button.pressValue)
{
pressed = true;
}
}
}
return pressed;
}
But before everything i call Input.Initialize() from another class (during Awake()). it looks like this :
public static void Initialize()
{
directInput = new DirectInput();
var joystickGuid = Guid.Empty;
foreach (var deviceInstance in directInput.GetDevices(SharpDX.DirectInput.DeviceType.Joystick, DeviceEnumerationFlags.AttachedOnly))
{
joystickGuid = deviceInstance.InstanceGuid;
}
if (joystickGuid == Guid.Empty)
{
foreach (var deviceInstance in directInput.GetDevices(SharpDX.DirectInput.DeviceType.Gamepad, DeviceEnumerationFlags.AttachedOnly))
{
joystickGuid = deviceInstance.InstanceGuid;
}
}
if (joystickGuid != Guid.Empty)
{
joystick = new Joystick(directInput, joystickGuid);
joystick.Properties.BufferSize = 128;
joystick.Acquire();
}
keyboard = new Keyboard(directInput);
keyboard.Properties.BufferSize = 128;
keyboard.Acquire();
}
Now to the problem. When i click to anything outside game window in the editor, keys does not respond anymore. I checked everything and both directInput and keyboard are still in variables. Most likely some problem with "Focus" of window because this problem looks like directInput instance or keyboard gets disconnected as soon as game window lost focus (focus is lost when window is not active window, active window is not "active" but so called "focused").
Do someone know why this happenig and how to repair it ?
EDIT : Looks like this problem is somehow connected to window(s). I have settings and i'm able to switch fullscreen runtime. As long as i'm in fullscreen it works fine but when i switch to window it stop working.
Thanks.
-Garrom
Now i see myself as very stupid person... Anyway i was right abou window focus. When game window lost focus it (somehow) break directInput. I solved this useing unity's callback OnApplicationFocus and re-Initialize (call Initialize(). See original question) every time game window gets focused.

Move Form onto specified Screen

I am trying to figure out how to move specified System.Windows.Forms.Form onto another than primary screen. I have ComboBox with list of available screens where user selects whichever screen he likes and my application is supposed to move one of its windows onto that screen.
I have only one screen on my laptop and no external monitor, so ComboBox on my computer offers only one option. I think minimalising desired window, moving it's left corner in the center of selected screen's Bounds and maximilising would do the job, right? I just can't test it. Is this a good way to go?
Thanks in advance!
Here's what I did, as a simple test...
I added a simple wrapper class so that I could change what happens on the ToString call (I only wanted to see the name listed in the combo box)
private class ScreenObj
{
public Screen screen = null;
public ScreenObj(Screen scr)
{
screen = scr;
}
public override string ToString()
{
return screen.DeviceName;
}
}
In the form load event I added this:
foreach(Screen screen in Screen.AllScreens)
{
cboScreens.Items.Add(new ScreenObj(screen));
}
And for the selected index change event of the combo box I had this:
private void cboScreens_SelectedIndexChanged(object sender, EventArgs e)
{
object o = cboScreens.SelectedItem;
if(null == o)
return;
ScreenObj scrObj = o as ScreenObj;
if(null == scrObj)
return;
Point p = new Point();
p.X = scrObj.screen.WorkingArea.Left;
p.Y = scrObj.screen.WorkingArea.Top;
this.Location = p;
}
It moved the form to the upper left hand corner of each of my screens.

Categories