Jump to content
  • Advertisement
Sign in to follow this  
Hurp

Unity Handling keyboard/mouse input

This topic is 2774 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

"Input Managers" are something that I see are commonly discussed in this forum, to a create extent in this thread. However, I typically see only keyboard events discussed and not mouse inputs such as x/y movement, scrolling and extra buttons (such as thumb buttons like Mouse5). I am trying to venture away from always using DirectX input to handle keyboard/mouse. Can anyone suggest a good way to set up handling input for mouse event, or even more ways to do keyboard events.

Any kind of explanation, or source code or tutorials would be very much appreciated.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
I am trying to venture away from always using DirectX input..

Good idea.

Unless you run into a particular problem, just use window messages (WM_KEYDOWN, WM_MOUSEMOVE, WM_VSCROLL, etc.).

Share this post


Link to post
Share on other sites
There is one issue that I can not grasp the concept of, and that is how "InputNotifiers" are used.

For example, I can see that typically when the "InputManager" detects that a key it pressed, it will send out a notifier. However, how is that notifier used? For example, is it attached to a class some how, or is an instance of it created and signed a function pointer it should call when a key is pressed?

Share this post


Link to post
Share on other sites
I say forget about these fancy "notifier" "listener" fancy shit and the classes. Just make it work. Maybe with one nasty disgusting switch statement and globals and every evil things. Your next input handler will be much nicer.

Share this post


Link to post
Share on other sites
An EventManager I wrote at one time maintained a vector of event/function pointer pairs. Events (with an accompanying callback function pointer) were registered (added to the vector) with the EventManager. On an event, the mgr iterated through the vector looking for requested events and calling the associated callback function.

I've never found a really good use for an event manager that complicated.

Similar to what szecs mentions, since then I just maintain a bunch of global booleans* for keystrokes of interest, and each object/class/function/etc. checks the globals as needed.

*E.g.,

case WM_KEYDOWN:
switch(LOWORD(wParam))
{
case VK_NUMPAD0: bNP0 = true; break;
case VK_NUMPAD1: bNP1 = true; break;
// etc.
case WM_KEYUP:
switch(LOWORD(wParam))
{
case VK_NUMPAD0: bNP0 = false; break;
case VK_NUMPAD1: bNP1 = false; break;
// etc.

where bNP0, bNP1, bNP2, etc., are just global bools.

Share this post


Link to post
Share on other sites
I would to have my InputManager not deal with global variables.

Here is how I was going to set it up, first I create a class known as InputNotifier. This class will take in a key, a function pointer to a KeyDown function and a function pointer to a KeyUp function.


#define INFUNCPTR(name) void (GameObject::*name)()
class InputNotifier
{
protected:
InputKey m_Key;

INFUNCPTR(m_OnKeyUp);
INFUNCPTR(m_OnKeyDown);

public:
InputNotifier(InputKey key, INFUNCPTR(onKeyUp), INFUNCPTR(onKeyDown))
{
key = key;
m_OnKeyUp = onKeyUp;
m_OnKeyDown = onKeyDown;
}
virtual ~InputNotifier() { }

virtual void OnKeyDown(LPARAM lParam)
{
m_OnKeyUp;
}

virtual void OnKeyUp(LPARAM lParam)
{
m_OnKeyDown;
}

InputKey GetKey() const { return m_Key; }
};



The second thing I would do is create a manager, to use with WinProc


class InputManager
{
protected:
vector<InputNotifier *> m_InputListeners;

public:
InputManager();
virtual ~InputManager();
bool AddListener(InputKey key, INFUNCPTR(onKeyUp), INFUNCPTR(onKeyDown));

void OnKeyDown(WPARAM wParam, LPARAM lParam);
void OnKeyUp(WPARAM wParam, LPARAM lParam);
};



The problem I am having is how do I hook in a function that would deal with objects that update based upon time? For example, I want my W key to move my camera up a little but, but that would require the current time slice, or approaching time slice.

Possible Fix 1: (Hack)
In could fix this by storing the last time slice, then use that when I press the W key ... but this seems like a hack.

Possible Fix 2: (Hackish).
In my message manager I store a queue of messages that require the time slice to be added in. The problem with doing this is that it would be a seperate list of messages to all of my other messages, meaning they may not get executed in order ... this could be very dangerous.

Does anyone have any suggestions on how this may be done?

Share this post


Link to post
Share on other sites
Quote:
I want my W key to move my camera up a little..

It's not very clear what problem you're trying to solve.

I would think, if the camera updates at some delta time, and W is down, move the camera at some speed times the delta time, regardless of when the key was pressed. Are you concerned that there will be some conflict (it's not clear) if the key was pressed just before the update so it really wasn't down for the entire delta time? Are your update times so long that it would make a difference?

Maybe a bit more explanation would help.

Share this post


Link to post
Share on other sites
Sorry about that, basically, I want to some how communicate to an object (my camera) that W has been pressed so it can preform a certain function.

The problem I am having is syncing up input with my update loop.

The way I use to have my update look when the input manager was not done through WndProc but rather DirectX was basically like this ...

------ Main Engine Update

float dt = gameTimer.fromLastUpdate()

if ( InputManager.buttonPressed(w) == true)
camera.moveForward(dt);

etc ...
------

Now, I am no longer checking to see if the button was pressed in the Main Engine update and I am not sure how to properly attach Input Notifiers to events (or actions).

Now, I could simply do the same thing, not use InputNotifier and queue all the inputs that are made into InputManager. However, I would like to process through the InputManagers keys pressed as they were pressed. For example, with the above approach you check things in order of however your if's end us using it. I would like to process my inputs in the order they happen.

Share this post


Link to post
Share on other sites
I was talking about nasty code, but you have to have a structure: decouple keyboard handling from the logic, if it's not event triggered.

I mean, if there's an event based action, put it into the keyboard handler, but if it's a regularly updated stuff: decouple.

I you want a certain time between the event handling (for example you waqnt to queue key-presses for a snake game), then I'd make my own keyboard queue, but only for the certain keys.


So in your example, I would use (non queued)
//update
float dt = gameTimer.fromLastUpdate()

if (MoveState.forward == TRUE )
camera.moveForward(dt);
...//event handling:
WM_KEYDOWN:
case 'W':
MoveState.forward = TRUE;
InputManager.buttonPressed = TRUE;
break;
...
// of course, use the OPP like setter/getters whatever


queued
...//event handling:

WM_KEYDOWN:
case 'W': case 'S': // and other keys you want buffed
CommandQueue.push(wParam);
break;

//update

float dt = gameTimer.fromLastUpdate()

...if ( time_passed_since_the_last_command_execution) // **sigh, I've just woken up )
ExecuteCommand(CommandQueue.pop());

Share this post


Link to post
Share on other sites
Hmm, interesting ... so on your queue example you don't even use a listener at all do you?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!