InputMaster Xbox 360 Controls

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(PlayerController, Re-reforged)
 
(13 intermediate revisions by one user not shown)
Line 3: Line 3:
 
=== Initial Notes ===
 
=== Initial Notes ===
 
* If you haven't read the primer tutorial, [http://wiki.unity3d.com/index.php/InputMaster_Primer go read that '''now'''] before reading this.
 
* If you haven't read the primer tutorial, [http://wiki.unity3d.com/index.php/InputMaster_Primer go read that '''now'''] before reading this.
 +
* Xbox 360 support is currently only for the Windows editor and for Windows builds.
 
* This tutorial is NOT a Unity tutorial nor a primer to C# or programming in general. This tutorial assumes that you already have a good grasp of how Unity works and that you have intimate knowledge of programming concepts and the C# language.
 
* This tutorial is NOT a Unity tutorial nor a primer to C# or programming in general. This tutorial assumes that you already have a good grasp of how Unity works and that you have intimate knowledge of programming concepts and the C# language.
 
* BSGTools is C# '''ONLY'''. Unityscript and Boo are '''NOT''' supported.
 
* BSGTools is C# '''ONLY'''. Unityscript and Boo are '''NOT''' supported.
Line 9: Line 10:
  
 
== Setting Up The Scene ==
 
== Setting Up The Scene ==
 +
We're going to base this scene off of the scene from [http://wiki.unity3d.com/index.php/InputMaster_Primer the primer tutorial].
 +
 +
Delete your InputManager script, as we're going to remake it in this tutorial.
 +
 +
Leave your PlayerController script, we'll be making major adjustments to it.
 +
 +
Make sure that the editor is targeting Standalone Windows for builds.
 +
 +
== Control Overview ==
 +
There are 3 types of XboxControls:
 +
 +
* XButtonControl
 +
** Has two bindings
 +
*** Positive - REQUIRED
 +
*** Negative - Optional
 +
** The bindings are of type XButton:
 +
*** A/B/X/Y Face Buttons
 +
*** Up/Down/Left/Right DPad
 +
*** The shoulder buttons
 +
*** The Back, Start and Guide buttons
 +
*** The Stick buttons (pressing in the analog sticks)
 +
** Conceptually identical to the KeyControl
 +
* XStickControl
 +
** Has one binding
 +
*** Positive - REQUIRED
 +
** The binding is of type XStick:
 +
*** Left Stick X Axis
 +
*** Left Stick Y Axis
 +
*** Right Stick X Axis
 +
*** Right Stick Y Axis
 +
* XTriggerControl
 +
** Has one binding
 +
*** Positive - REQUIRED
 +
** The binding is of type XTrigger
 +
*** Left Trigger
 +
*** Right Trigger
 +
** Functions as you expect. Does not have Unity's flaw of the Triggers being interpreted as one axis.
 +
 +
== Creating the Controls ==
 +
 +
Create a new InputManager script like the one from the primer tutorial, except stop after you've set up the InputMaster instance.
 +
 +
We're going to recreate the KeyControls in order, all at once.
 +
 +
You'll need to add a '''using''' statement for ''BSGTools.IO.Xbox''. Create the following four Xbox Controls:
 +
 +
* XButtonControl - Our color changer.
 +
* XTriggerControl - Our resizer.
 +
* 2 XStickControls - One for each axis of the left stick for movement.
 +
 +
Feel free to assign whatever bindings you want. In the end, you should have something like this:
 +
 +
<syntaxhighlight lang="csharp">
 +
using UnityEngine;
 +
using BSGTools.IO;
 +
using BSGTools.Structure;
 +
using BSGTools.IO.Xbox;
 +
 +
public class InputManager : Singleton<InputManager> {
 +
 +
public InputMaster Master { get; private set; }
 +
 +
public XButtonControl xChangeColor = new XButtonControl(XButton.A) {
 +
Name = "Xbox Change Color"
 +
};
 +
public XStickControl xStrafe = new XStickControl(XStick.StickLeftX) {
 +
Name = "Xbox Strafe"
 +
};
 +
public XStickControl xMoveFB = new XStickControl(XStick.StickLeftX) {
 +
Name = "Xbox Move Forward/Back"
 +
};
 +
public XTriggerControl xScaleUp = new XTriggerControl(XTrigger.TriggerRight) {
 +
Name = "Xbox Resize"
 +
};
 +
 +
void Awake() {
 +
Master = InputMaster.CreateMaster(this);
 +
}
 +
}
 +
</syntaxhighlight>
 +
 +
== PlayerController, Reforged ==
 +
 +
By now you must have a bunch of fun errors in your PlayerController script.
 +
 +
The switch between using KeyControls and Xbox Controls is simple as pie, just switch the variable names and you're set. Everything else works just the same. Your final Update method should look like so:
 +
 +
<syntaxhighlight lang="csharp">
 +
void Update() {
 +
var io = InputManager.Instance;
 +
 +
if(io.xChangeColor.Down == ControlState.Positive)
 +
renderer.material.color = new Color(Random.value, Random.value, Random.value);
 +
 +
//When xScaleUp.Value == 0, we're adding nothing to the original scale.
 +
//When xScaleUp.Value == 1, we're adding the full value of scaleAdditive to the original scale.
 +
transform.localScale = originalScale + (scaleAdditive * io.xScaleUp.Value);
 +
 +
var position = transform.position;
 +
//While InputMaster uses Time.deltaTime to smooth values, not including it here
 +
//makes controlling values like this overly sensitive.
 +
position.x += io.xStrafe.Value * Time.deltaTime * moveSpeed;
 +
position.y += io.xMoveFB.Value * Time.deltaTime * moveSpeed;
 +
 +
position.x = Mathf.Clamp(position.x, -maxPosition.x, maxPosition.x);
 +
position.y = Mathf.Clamp(position.y, -maxPosition.y, maxPosition.y);
 +
transform.position = position;
 +
}
 +
</syntaxhighlight>
 +
 +
== Multiplayer Madness ==
 +
=== InputManager ===
 +
Here's how easy it is to turn your single player game into a 2-4 player game. Didn't ask for it? Too bad, you're getting it.
 +
 +
Our first stop is in InputManager. We're going to convert our Xbox Control objects into arrays and instantiate the values using a really cool helper function. For example, our XButtonControl will look like this:
 +
 +
<syntaxhighlight lang="csharp">
 +
public XButtonControl[] xChangeColor = XButtonControl.CreateMultiple(4, new XButtonControl(XButton.A) {
 +
Name = "Xbox Change Color"
 +
});
 +
</syntaxhighlight>
 +
 +
As you can see, our XButtonControl is now an array of XButtonControl[]. The core of what we had there is exactly the same, except now it's wrapped in the XButtonControl.CreateMultiple(byte, XButtonControl) function. All that function does is takes a "template" control that you provide (the second argument), creates clones of it, throws away the template control and returns an array of new controls. Each control in the array is bound to a controller index. For example, the controller in slot 1 will be index 0 in the array of controls, slot 2 will be index 1, etc..
 +
 +
This is set up this way to make getting controller values as easy as possible.
 +
 +
Following this pattern, your controls should look like this:
 +
 +
<syntaxhighlight lang="csharp">
 +
using UnityEngine;
 +
using BSGTools.IO;
 +
using BSGTools.IO.Xbox;
 +
using BSGTools.Structure;
 +
 +
public class InputManager : Singleton<InputManager> {
 +
 +
public InputMaster Master { get; private set; }
 +
 +
public XButtonControl[] xChangeColor = XButtonControl.CreateMultiple(4, new XButtonControl(XButton.A) {
 +
Name = "Xbox Change Color"
 +
});
 +
public XStickControl[] xStrafe = XStickControl.CreateMultiple(4, new XStickControl(XStick.StickLeftX) {
 +
Name = "Xbox Strafe"
 +
});
 +
public XStickControl[] xMoveFB = XStickControl.CreateMultiple(4, new XStickControl(XStick.StickLeftX) {
 +
Name = "Xbox Move Forward/Back"
 +
});
 +
public XTriggerControl[] xScaleUp = XTriggerControl.CreateMultiple(4, new XTriggerControl(XTrigger.TriggerRight) {
 +
Name = "Xbox Resize"
 +
});
 +
 +
void Awake() {
 +
Master = InputMaster.CreateMaster(this);
 +
}
 +
}
 +
</syntaxhighlight>
 +
 +
=== PlayerController, Re-reforged ===
 +
 +
Let's add to our PlayerController so that this script can be attached to multiple players and work without any logic changes.
 +
 +
We're going to add a private byte to store our player index, then adjust how we access our control.
 +
 +
I'm going to make sure that we can't assign a player index outside of the 0...3 range (4 possible controller slots). Here's our player index:
 +
 +
<syntaxhighlight lang="csharp">
 +
[SerializeField, Range(0, 3)]
 +
private sbyte playerIndex;
 +
</syntaxhighlight>
 +
 +
Now that will be assignable in the Inspector with a nice, safe slider.
 +
 +
Then we just have to adjust how we access our controls. In our '''Update''' function, We'll create a new local version of each control, using our playerIndex to grab the right control for the right controller index:
 +
 +
<syntaxhighlight lang="csharp">
 +
var xChangeColor = io.xChangeColor[playerIndex];
 +
var xScaleUp = io.xScaleUp[playerIndex];
 +
var xStrafe = io.xStrafe[playerIndex];
 +
var xMoveFB = io.xMoveFB[playerIndex];
 +
</syntaxhighlight>
 +
 +
In the rest of the '''Update''' function, remove the ''io.'' from each control call. In the end, the logic should look like this:
 +
 +
<syntaxhighlight lang="csharp">
 +
if(xChangeColor.Down == ControlState.Positive)
 +
renderer.material.color = new Color(Random.value, Random.value, Random.value);
 +
 +
//When xScaleUp.Value == 0, we're adding nothing to the original scale.
 +
//When xScaleUp.Value == 1, we're adding the full value of scaleAdditive to the original scale.
 +
transform.localScale = originalScale + (scaleAdditive * xScaleUp.Value);
 +
 +
Vector3 position = transform.position;
 +
//While InputMaster uses Time.deltaTime to smooth values, not including it here
 +
//makes controlling values like this overly sensitive.
 +
position.x += xStrafe.Value * Time.deltaTime * moveSpeed;
 +
position.y += xMoveFB.Value * Time.deltaTime * moveSpeed;
 +
 +
position.x = Mathf.Clamp(position.x, -maxPosition.x, maxPosition.x);
 +
position.y = Mathf.Clamp(position.y, -maxPosition.y, maxPosition.y);
 +
 +
transform.position = position;
 +
</syntaxhighlight>
 +
 +
Unfortunately the only way to test the functionality is with multiple Xbox controllers hooked up to your system. However, if you created 3 additional Player objects, attached a PlayerController to each and gave each one a unique playerIndex, you'd have yourself a 4 player... color changing... size adjusting... death match?

Latest revision as of 21:18, 6 November 2014

Contents

[edit] InputMaster Xbox 360 Controls

Relevant for version v7.1.1b

[edit] Initial Notes

  • If you haven't read the primer tutorial, go read that now before reading this.
  • Xbox 360 support is currently only for the Windows editor and for Windows builds.
  • This tutorial is NOT a Unity tutorial nor a primer to C# or programming in general. This tutorial assumes that you already have a good grasp of how Unity works and that you have intimate knowledge of programming concepts and the C# language.
  • BSGTools is C# ONLY. Unityscript and Boo are NOT supported.
  • InputMaster was designed for programmers, by a programmer. It has no configurable options in the Inspector, and should not be manually added to a GameObject for any reason. All configuration is done in code. However, if you'd like to make some variables editable in the Inspector, you can expose them through your InputManager.
  • It is worth mentioning that this tutorial uses a Singleton pattern to provide access to the InputManager script we will be creating. This pattern is easy and fast to implement, which is why I'm using it here. Some people argue that the Singleton pattern is bad design. Regardless, this is a beginner's tutorial, and I'll be treating it as such.

[edit] Setting Up The Scene

We're going to base this scene off of the scene from the primer tutorial.

Delete your InputManager script, as we're going to remake it in this tutorial.

Leave your PlayerController script, we'll be making major adjustments to it.

Make sure that the editor is targeting Standalone Windows for builds.

[edit] Control Overview

There are 3 types of XboxControls:

  • XButtonControl
    • Has two bindings
      • Positive - REQUIRED
      • Negative - Optional
    • The bindings are of type XButton:
      • A/B/X/Y Face Buttons
      • Up/Down/Left/Right DPad
      • The shoulder buttons
      • The Back, Start and Guide buttons
      • The Stick buttons (pressing in the analog sticks)
    • Conceptually identical to the KeyControl
  • XStickControl
    • Has one binding
      • Positive - REQUIRED
    • The binding is of type XStick:
      • Left Stick X Axis
      • Left Stick Y Axis
      • Right Stick X Axis
      • Right Stick Y Axis
  • XTriggerControl
    • Has one binding
      • Positive - REQUIRED
    • The binding is of type XTrigger
      • Left Trigger
      • Right Trigger
    • Functions as you expect. Does not have Unity's flaw of the Triggers being interpreted as one axis.

[edit] Creating the Controls

Create a new InputManager script like the one from the primer tutorial, except stop after you've set up the InputMaster instance.

We're going to recreate the KeyControls in order, all at once.

You'll need to add a using statement for BSGTools.IO.Xbox. Create the following four Xbox Controls:

  • XButtonControl - Our color changer.
  • XTriggerControl - Our resizer.
  • 2 XStickControls - One for each axis of the left stick for movement.

Feel free to assign whatever bindings you want. In the end, you should have something like this:

using UnityEngine;
using BSGTools.IO;
using BSGTools.Structure;
using BSGTools.IO.Xbox;
 
public class InputManager : Singleton<InputManager> {
 
	public InputMaster Master { get; private set; }
 
	public XButtonControl xChangeColor = new XButtonControl(XButton.A) {
		Name = "Xbox Change Color"
	};
	public XStickControl xStrafe = new XStickControl(XStick.StickLeftX) {
		Name = "Xbox Strafe"
	};
	public XStickControl xMoveFB = new XStickControl(XStick.StickLeftX) {
		Name = "Xbox Move Forward/Back"
	};
	public XTriggerControl xScaleUp = new XTriggerControl(XTrigger.TriggerRight) {
		Name = "Xbox Resize"
	};
 
	void Awake() {
		Master = InputMaster.CreateMaster(this);
	}
}

[edit] PlayerController, Reforged

By now you must have a bunch of fun errors in your PlayerController script.

The switch between using KeyControls and Xbox Controls is simple as pie, just switch the variable names and you're set. Everything else works just the same. Your final Update method should look like so:

void Update() {
	var io = InputManager.Instance;
 
	if(io.xChangeColor.Down == ControlState.Positive)
		renderer.material.color = new Color(Random.value, Random.value, Random.value);
 
	//When xScaleUp.Value == 0, we're adding nothing to the original scale.
	//When xScaleUp.Value == 1, we're adding the full value of scaleAdditive to the original scale.
	transform.localScale = originalScale + (scaleAdditive * io.xScaleUp.Value);
 
	var position = transform.position;
	//While InputMaster uses Time.deltaTime to smooth values, not including it here
	//makes controlling values like this overly sensitive.
	position.x += io.xStrafe.Value * Time.deltaTime * moveSpeed;
	position.y += io.xMoveFB.Value * Time.deltaTime * moveSpeed;
 
	position.x = Mathf.Clamp(position.x, -maxPosition.x, maxPosition.x);
	position.y = Mathf.Clamp(position.y, -maxPosition.y, maxPosition.y);
	transform.position = position;
}

[edit] Multiplayer Madness

[edit] InputManager

Here's how easy it is to turn your single player game into a 2-4 player game. Didn't ask for it? Too bad, you're getting it.

Our first stop is in InputManager. We're going to convert our Xbox Control objects into arrays and instantiate the values using a really cool helper function. For example, our XButtonControl will look like this:

public XButtonControl[] xChangeColor = XButtonControl.CreateMultiple(4, new XButtonControl(XButton.A) {
	Name = "Xbox Change Color"
});

As you can see, our XButtonControl is now an array of XButtonControl[]. The core of what we had there is exactly the same, except now it's wrapped in the XButtonControl.CreateMultiple(byte, XButtonControl) function. All that function does is takes a "template" control that you provide (the second argument), creates clones of it, throws away the template control and returns an array of new controls. Each control in the array is bound to a controller index. For example, the controller in slot 1 will be index 0 in the array of controls, slot 2 will be index 1, etc..

This is set up this way to make getting controller values as easy as possible.

Following this pattern, your controls should look like this:

using UnityEngine;
using BSGTools.IO;
using BSGTools.IO.Xbox;
using BSGTools.Structure;
 
public class InputManager : Singleton<InputManager> {
 
	public InputMaster Master { get; private set; }
 
	public XButtonControl[] xChangeColor = XButtonControl.CreateMultiple(4, new XButtonControl(XButton.A) {
		Name = "Xbox Change Color"
	});
	public XStickControl[] xStrafe = XStickControl.CreateMultiple(4, new XStickControl(XStick.StickLeftX) {
		Name = "Xbox Strafe"
	});
	public XStickControl[] xMoveFB = XStickControl.CreateMultiple(4, new XStickControl(XStick.StickLeftX) {
		Name = "Xbox Move Forward/Back"
	});
	public XTriggerControl[] xScaleUp = XTriggerControl.CreateMultiple(4, new XTriggerControl(XTrigger.TriggerRight) {
		Name = "Xbox Resize"
	});
 
	void Awake() {
		Master = InputMaster.CreateMaster(this);
	}
}

[edit] PlayerController, Re-reforged

Let's add to our PlayerController so that this script can be attached to multiple players and work without any logic changes.

We're going to add a private byte to store our player index, then adjust how we access our control.

I'm going to make sure that we can't assign a player index outside of the 0...3 range (4 possible controller slots). Here's our player index:

[SerializeField, Range(0, 3)]
private sbyte playerIndex;

Now that will be assignable in the Inspector with a nice, safe slider.

Then we just have to adjust how we access our controls. In our Update function, We'll create a new local version of each control, using our playerIndex to grab the right control for the right controller index:

var xChangeColor = io.xChangeColor[playerIndex];
var xScaleUp = io.xScaleUp[playerIndex];
var xStrafe = io.xStrafe[playerIndex];
var xMoveFB = io.xMoveFB[playerIndex];

In the rest of the Update function, remove the io. from each control call. In the end, the logic should look like this:

if(xChangeColor.Down == ControlState.Positive)
	renderer.material.color = new Color(Random.value, Random.value, Random.value);
 
//When xScaleUp.Value == 0, we're adding nothing to the original scale.
//When xScaleUp.Value == 1, we're adding the full value of scaleAdditive to the original scale.
transform.localScale = originalScale + (scaleAdditive * xScaleUp.Value);
 
Vector3 position = transform.position;
//While InputMaster uses Time.deltaTime to smooth values, not including it here
//makes controlling values like this overly sensitive.
position.x += xStrafe.Value * Time.deltaTime * moveSpeed;
position.y += xMoveFB.Value * Time.deltaTime * moveSpeed;
 
position.x = Mathf.Clamp(position.x, -maxPosition.x, maxPosition.x);
position.y = Mathf.Clamp(position.y, -maxPosition.y, maxPosition.y);
 
transform.position = position;

Unfortunately the only way to test the functionality is with multiple Xbox controllers hooked up to your system. However, if you created 3 additional Player objects, attached a PlayerController to each and gave each one a unique playerIndex, you'd have yourself a 4 player... color changing... size adjusting... death match?

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox