@@ -807,6 +807,64 @@ public void PlayerInput_PlayerIndex_DoesNotChange()
807807 Assert . That ( playerInput2 . playerIndex , Is . EqualTo ( 1 ) ) ;
808808 }
809809
810+ [ Test ]
811+ [ Category ( "PlayerInput" ) ]
812+ [ TestCase ( PlayerNotifications . SendMessages , typeof ( MessageListener ) ) ]
813+ [ TestCase ( PlayerNotifications . BroadcastMessages , typeof ( MessageListener ) ) ]
814+ [ TestCase ( PlayerNotifications . InvokeUnityEvents , typeof ( PlayerInputEventListener ) , true ) ]
815+ [ TestCase ( PlayerNotifications . InvokeCSharpEvents , typeof ( PlayerInputCSharpEventListener ) , true ) ]
816+ public void PlayerInput_CanReceiveNotificationWhenActionIsTriggered ( PlayerNotifications notificationBehavior , Type listenerType , bool receivesAllPhases = false )
817+ {
818+ var gamepad = InputSystem . AddDevice < Gamepad > ( ) ;
819+
820+ var go = new GameObject ( ) ;
821+ go . SetActive ( false ) ;
822+ IListener listener ;
823+ if ( notificationBehavior == PlayerNotifications . BroadcastMessages )
824+ {
825+ var child = new GameObject ( ) ;
826+ child . transform . parent = go . transform ;
827+ listener = ( IListener ) child . AddComponent ( listenerType ) ;
828+ }
829+ else
830+ {
831+ listener = ( IListener ) go . AddComponent ( listenerType ) ;
832+ }
833+ var playerInput = go . AddComponent < PlayerInput > ( ) ;
834+
835+ playerInput . notificationBehavior = notificationBehavior ;
836+ playerInput . defaultActionMap = "gameplay" ;
837+ playerInput . actions = InputActionAsset . FromJson ( kActions ) ;
838+
839+ go . SetActive ( true ) ;
840+
841+ Press ( gamepad . buttonSouth ) ;
842+
843+ if ( receivesAllPhases )
844+ {
845+ Assert . That ( listener . messages , Is . EquivalentTo ( new [ ] { new Message ( "Fire Started" , 1f ) , new Message ( "Fire Performed" , 1f ) } ) ) ;
846+ }
847+ else
848+ {
849+ Assert . That ( listener . messages , Is . EquivalentTo ( new [ ] { new Message ( "OnFire" , 1f ) } ) ) ;
850+ }
851+
852+ listener . messages . Clear ( ) ;
853+
854+ Release ( gamepad . buttonSouth ) ;
855+
856+ if ( receivesAllPhases )
857+ {
858+ Assert . That ( listener . messages , Is . EquivalentTo ( new [ ] { new Message ( "Fire Canceled" , 0f ) } ) ) ;
859+ }
860+ else
861+ {
862+ // 'Fire' is a button action. Unlike with value actions, PlayerInput should not
863+ // send a message on button release (i.e. when the action cancels).
864+ Assert . That ( listener . messages , Is . Empty ) ;
865+ }
866+ }
867+
810868 [ Test ]
811869 [ Category ( "PlayerInput" ) ]
812870 public void PlayerInput_CanReceiveMessageWhenActionIsTriggered ( )
@@ -836,7 +894,7 @@ public void PlayerInput_CanReceiveMessageWhenActionIsTriggered()
836894
837895 [ Test ]
838896 [ Category ( "PlayerInput" ) ]
839- public void PlayerInput_CanReceiveMessageWhenContinuousActionIsCanceled ( )
897+ public void PlayerInput_CanReceiveMessageWhenValueActionIsCanceled ( )
840898 {
841899 var gamepad = InputSystem . AddDevice < Gamepad > ( ) ;
842900
@@ -867,26 +925,6 @@ public void PlayerInput_CanReceiveMessageWhenContinuousActionIsCanceled()
867925 } ) ) ;
868926 }
869927
870- [ Test ]
871- [ Category ( "PlayerInput" ) ]
872- public void PlayerInput_CanReceiveEventWhenActionIsTriggered ( )
873- {
874- var gamepad = InputSystem . AddDevice < Gamepad > ( ) ;
875-
876- var go = new GameObject ( ) ;
877- var listener = go . AddComponent < MessageListener > ( ) ;
878- var playerInput = go . AddComponent < PlayerInput > ( ) ;
879- playerInput . notificationBehavior = PlayerNotifications . InvokeUnityEvents ;
880- playerInput . defaultActionMap = "gameplay" ;
881- playerInput . actions = InputActionAsset . FromJson ( kActions ) ;
882- listener . SetUpEvents ( playerInput ) ;
883-
884- Press ( gamepad . buttonSouth ) ;
885-
886- Assert . That ( listener . messages ,
887- Is . EquivalentTo ( new [ ] { new Message ( "gameplay/fire Started" , 1f ) , new Message ( "gameplay/fire Performed" , 1f ) } ) ) ;
888- }
889-
890928 [ Test ]
891929 [ Category ( "PlayerInput" ) ]
892930 [ TestCase ( PlayerNotifications . SendMessages , typeof ( MessageListener ) ) ]
@@ -1411,9 +1449,9 @@ public void TODO_PlayerInput_TriggeringAction_DoesNotAllocate()
14111449 {
14121450 ""name"" : ""gameplay"",
14131451 ""actions"" : [
1414- { ""name"" : ""fire "", ""type"" : ""button"" },
1415- { ""name"" : ""look "", ""type"" : ""value"" },
1416- { ""name"" : ""move "", ""type"" : ""value"" }
1452+ { ""name"" : ""Fire "", ""type"" : ""button"" },
1453+ { ""name"" : ""Look "", ""type"" : ""value"" },
1454+ { ""name"" : ""Move "", ""type"" : ""value"" }
14171455 ],
14181456 ""bindings"" : [
14191457 { ""path"" : ""<Gamepad>/buttonSouth"", ""action"" : ""fire"", ""groups"" : ""Gamepad"" },
@@ -1516,43 +1554,6 @@ private class MessageListener : MonoBehaviour, IListener
15161554 {
15171555 public List < Message > messages { get ; } = new List < Message > ( ) ;
15181556
1519- public void SetUpEvents ( PlayerInput player )
1520- {
1521- var fireAction = player . actions . FindAction ( "gameplay/fire" ) ;
1522- var lookAction = player . actions . FindAction ( "gameplay/look" ) ;
1523- var moveAction = player . actions . FindAction ( "gameplay/move" ) ;
1524-
1525- var fireEvent = new PlayerInput . ActionEvent ( fireAction ) ;
1526- var lookEvent = new PlayerInput . ActionEvent ( lookAction ) ;
1527- var moveEvent = new PlayerInput . ActionEvent ( moveAction ) ;
1528-
1529- fireEvent . AddListener ( OnFireEvent ) ;
1530- lookEvent . AddListener ( OnLookEvent ) ;
1531- moveEvent . AddListener ( OnMoveEvent ) ;
1532-
1533- player . actionEvents = new [ ]
1534- {
1535- fireEvent ,
1536- lookEvent ,
1537- moveEvent ,
1538- } ;
1539- }
1540-
1541- private void OnFireEvent ( InputAction . CallbackContext context )
1542- {
1543- messages . Add ( new Message { name = "gameplay/fire " + context . phase , value = context . ReadValue < float > ( ) } ) ;
1544- }
1545-
1546- private void OnLookEvent ( InputAction . CallbackContext context )
1547- {
1548- messages . Add ( new Message { name = "gameplay/look " + context . phase , value = context . ReadValue < Vector2 > ( ) } ) ;
1549- }
1550-
1551- private void OnMoveEvent ( InputAction . CallbackContext context )
1552- {
1553- messages . Add ( new Message { name = "gameplay/move" + context . phase , value = context . ReadValue < Vector2 > ( ) } ) ;
1554- }
1555-
15561557 // ReSharper disable once UnusedMember.Local
15571558 public void OnFire ( InputValue value )
15581559 {
@@ -1614,16 +1615,50 @@ public void OnEnable()
16141615 var playerInput = GetComponent < PlayerInput > ( ) ;
16151616 Debug . Assert ( playerInput != null , "Must have PlayerInput component" ) ;
16161617
1617- foreach ( var item in playerInput . actionEvents )
1618- item . AddListener ( OnAction ) ;
1618+ SetUpActionEvents ( playerInput ) ;
16191619
16201620 playerInput . deviceLostEvent . AddListener ( OnDeviceLost ) ;
16211621 playerInput . deviceRegainedEvent . AddListener ( OnDeviceRegained ) ;
16221622 }
16231623
1624- private void OnAction ( InputAction . CallbackContext context )
1624+ private void SetUpActionEvents ( PlayerInput player )
16251625 {
1626- messages . Add ( new Message ( context . action . ToString ( ) ) ) ;
1626+ var fireAction = player . actions . FindAction ( "gameplay/fire" ) ;
1627+ var lookAction = player . actions . FindAction ( "gameplay/look" ) ;
1628+ var moveAction = player . actions . FindAction ( "gameplay/move" ) ;
1629+
1630+ var fireEvent = new PlayerInput . ActionEvent ( fireAction ) ;
1631+ var lookEvent = new PlayerInput . ActionEvent ( lookAction ) ;
1632+ var moveEvent = new PlayerInput . ActionEvent ( moveAction ) ;
1633+
1634+ fireEvent . AddListener ( OnFireEvent ) ;
1635+ lookEvent . AddListener ( OnLookEvent ) ;
1636+ moveEvent . AddListener ( OnMoveEvent ) ;
1637+
1638+ player . actionEvents = new [ ]
1639+ {
1640+ fireEvent ,
1641+ lookEvent ,
1642+ moveEvent ,
1643+ } ;
1644+ }
1645+
1646+ // We have separate methods for these rather than one that we reuse for each listener in order to
1647+ // guarantee that PlayerInput is indeed calling the right method.
1648+
1649+ private void OnFireEvent ( InputAction . CallbackContext context )
1650+ {
1651+ messages . Add ( new Message ( $ "Fire { context . phase } ", context . ReadValueAsObject ( ) ) ) ;
1652+ }
1653+
1654+ private void OnLookEvent ( InputAction . CallbackContext context )
1655+ {
1656+ messages . Add ( new Message ( $ "Look { context . phase } ", context . ReadValueAsObject ( ) ) ) ;
1657+ }
1658+
1659+ private void OnMoveEvent ( InputAction . CallbackContext context )
1660+ {
1661+ messages . Add ( new Message ( $ "Move { context . phase } ", context . ReadValueAsObject ( ) ) ) ;
16271662 }
16281663
16291664 private void OnDeviceLost ( PlayerInput player )
@@ -1648,15 +1683,14 @@ public void OnEnable()
16481683 var playerInput = GetComponent < PlayerInput > ( ) ;
16491684 Debug . Assert ( playerInput != null , "Must have PlayerInput component" ) ;
16501685
1651-
16521686 playerInput . onActionTriggered += OnAction ;
16531687 playerInput . onDeviceLost += OnDeviceLost ;
16541688 playerInput . onDeviceRegained += OnDeviceRegained ;
16551689 }
16561690
16571691 private void OnAction ( InputAction . CallbackContext context )
16581692 {
1659- messages . Add ( new Message ( context . action . ToString ( ) ) ) ;
1693+ messages . Add ( new Message ( $ " { context . action . name } { context . phase } " , context . ReadValueAsObject ( ) ) ) ;
16601694 }
16611695
16621696 private void OnDeviceLost ( PlayerInput player )
0 commit comments