Skip to content

Fix issue with queuing input events that stomp on others. #5034

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DevProject/Packages/packages-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"url": "https://artifactory.prd.cds.internal.unity3d.com/artifactory/api/npm/upm-candidates"
},
"com.unity.barracuda": {
"version": "1.3.0-preview",
"version": "1.3.1-preview",
"depth": 1,
"source": "registry",
"dependencies": {
Expand Down Expand Up @@ -108,7 +108,7 @@
"depth": 0,
"source": "local",
"dependencies": {
"com.unity.barracuda": "1.3.0-preview",
"com.unity.barracuda": "1.3.1-preview",
"com.unity.modules.imageconversion": "1.0.0",
"com.unity.modules.jsonserialize": "1.0.0",
"com.unity.modules.physics": "1.0.0",
Expand All @@ -121,7 +121,7 @@
"depth": 0,
"source": "local",
"dependencies": {
"com.unity.ml-agents": "1.7.2-preview"
"com.unity.ml-agents": "1.8.0-preview"
}
},
"com.unity.multiplayer-hlapi": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Unity.MLAgents.Actuators;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;

namespace Unity.MLAgents.Extensions.Input
Expand All @@ -26,11 +27,11 @@ public ActionSpec GetActionSpecForInputAction(InputAction action)
}

/// TODO again this might need to be more nuanced for things like continuous buttons.
/// <inheritdoc cref="IRLActionInputAdaptor.QueueInputEventForAction"/>
public void QueueInputEventForAction(InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/>
public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
{
var val = actionBuffers.DiscreteActions[0];
InputSystem.QueueDeltaStateEvent(control, (byte)val);
((ButtonControl)control).WriteValueIntoEvent((float)val, eventPtr);
}

/// <inheritdoc cref="IRLActionInputAdaptor.WriteToHeuristic"/>>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#if MLA_INPUT_SYSTEM && UNITY_2019_4_OR_NEWER
using Unity.MLAgents.Actuators;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;

namespace Unity.MLAgents.Extensions.Input
Expand All @@ -16,11 +17,11 @@ public ActionSpec GetActionSpecForInputAction(InputAction action)
return ActionSpec.MakeContinuous(1);
}

/// <inheritdoc cref="IRLActionInputAdaptor.QueueInputEventForAction"/>
public void QueueInputEventForAction(InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/>
public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
{
var val = actionBuffers.ContinuousActions[0];
InputSystem.QueueDeltaStateEvent(control,(double)val);
((DoubleControl)control).WriteValueIntoEvent((double)val, eventPtr);
}

/// <inheritdoc cref="IRLActionInputAdaptor.WriteToHeuristic"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ public ActionSpec GetActionSpecForInputAction(InputAction action)
return ActionSpec.MakeContinuous(1);
}

/// <inheritdoc cref="IRLActionInputAdaptor.QueueInputEventForAction"/>
public void QueueInputEventForAction(InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/>
public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
{
var val = actionBuffers.ContinuousActions[0];
InputSystem.QueueDeltaStateEvent(control, val);
control.WriteValueIntoEvent(val, eventPtr);
}

/// <inheritdoc cref="IRLActionInputAdaptor.WriteToHeuristic"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ public ActionSpec GetActionSpecForInputAction(InputAction action)
return ActionSpec.MakeDiscrete(2);
}

/// <inheritdoc cref="IRLActionInputAdaptor.QueueInputEventForAction"/>
public void QueueInputEventForAction(InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/>
public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers)
{
var val = actionBuffers.DiscreteActions[0];
InputSystem.QueueDeltaStateEvent(control, val);
control.WriteValueIntoEvent(val, eventPtr);
}

/// <inheritdoc cref="IRLActionInputAdaptor.WriteToHeuristic"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Unity.MLAgents.Actuators;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;

namespace Unity.MLAgents.Extensions.Input
Expand All @@ -19,15 +20,15 @@ public ActionSpec GetActionSpecForInputAction(InputAction action)
return ActionSpec.MakeContinuous(2);
}

/// <inheritdoc cref="IRLActionInputAdaptor.QueueInputEventForAction"/>
public void QueueInputEventForAction(InputAction action,
/// <inheritdoc cref="IRLActionInputAdaptor.WriteToInputEventForAction"/>
public void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action,
InputControl control,
ActionSpec actionSpec,
in ActionBuffers actionBuffers)
{
var x = actionBuffers.ContinuousActions[0];
var y = actionBuffers.ContinuousActions[1];
InputSystem.QueueDeltaStateEvent(control, new Vector2(x, y));
control.WriteValueIntoEvent(new Vector2(x, y), eventPtr);
}

/// <inheritdoc cref="IRLActionInputAdaptor.WriteToHeuristic"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using Unity.MLAgents.Actuators;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;

namespace Unity.MLAgents.Extensions.Input
{
Expand All @@ -22,11 +23,12 @@ public interface IRLActionInputAdaptor
/// <summary>
/// Translates data from the <see cref="ActionBuffers"/> object to the <see cref="InputSystem"/>.
/// </summary>
/// <param name="eventPtr">The Event pointer to write to.</param>
/// <param name="action">The action associated with this adaptor.</param>
/// <param name="control">The control which will write the event to the <see cref="InputSystem"/>.</param>
/// <param name="actionSpec">The <see cref="ActionSpec"/> associated with this action and adaptor pair.</param>
/// <param name="actionBuffers">The <see cref="ActionBuffers"/> object to read from.</param>
void QueueInputEventForAction(InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers);
void WriteToInputEventForAction(InputEventPtr eventPtr, InputAction action, InputControl control, ActionSpec actionSpec, in ActionBuffers actionBuffers);

/// <summary>
/// Writes data from the <paramref name="action"/> to the <paramref name="actionBuffers"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public class InputActionActuator : IActuator, IHeuristicProvider, IBuiltInActuat
readonly BehaviorParameters m_BehaviorParameters;
readonly InputAction m_Action;
readonly IRLActionInputAdaptor m_InputAdaptor;
InputActuatorEventContext m_InputActuatorEventContext;
InputDevice m_Device;
InputControl m_Control;

Expand All @@ -34,14 +35,17 @@ public class InputActionActuator : IActuator, IHeuristicProvider, IBuiltInActuat
/// via the <see cref="IRLActionInputAdaptor"/>.</param>
/// <param name="adaptor">The <see cref="IRLActionInputAdaptor"/> that will convert data between ML-Agents
/// and the <see cref="InputSystem"/>.</param>
/// <param name="inputActuatorEventContext">The object that will provide the event ptr to write to.</param>
public InputActionActuator(InputDevice inputDevice, BehaviorParameters behaviorParameters,
InputAction action,
IRLActionInputAdaptor adaptor)
IRLActionInputAdaptor adaptor,
InputActuatorEventContext inputActuatorEventContext)
{
m_BehaviorParameters = behaviorParameters;
Name = $"InputActionActuator-{action.name}";
m_Action = action;
m_InputAdaptor = adaptor;
m_InputActuatorEventContext = inputActuatorEventContext;
ActionSpec = adaptor.GetActionSpecForInputAction(m_Action);
m_Device = inputDevice;
m_Control = m_Device?.GetChildControl(m_Action.name);
Expand All @@ -53,7 +57,11 @@ public void OnActionReceived(ActionBuffers actionBuffers)
Profiler.BeginSample("InputActionActuator.OnActionReceived");
if (!m_BehaviorParameters.IsInHeuristicMode())
{
m_InputAdaptor.QueueInputEventForAction(m_Action, m_Control, ActionSpec, actionBuffers);
using (m_InputActuatorEventContext.GetEventForFrame(out var eventPtr))
{
m_InputAdaptor.WriteToInputEventForAction(eventPtr, m_Action, m_Control, ActionSpec, actionBuffers);
}

}
Profiler.EndSample();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
#if MLA_INPUT_SYSTEM && UNITY_2019_4_OR_NEWER
using System;
using System.Collections.Generic;
using Unity.Collections;
using Unity.MLAgents.Actuators;
using Unity.MLAgents.Policies;
using UnityEngine;
using UnityEngine.Assertions;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.InputSystem.Layouts;
using UnityEngine.InputSystem.Utilities;
#if UNITY_EDITOR
Expand Down Expand Up @@ -57,9 +59,18 @@ public override ActionSpec ActionSpec
get
{
#if UNITY_EDITOR
FindNeededComponents();
var actuators = CreateActuatorsFromMap(m_InputAsset.FindActionMap(m_PlayerInput.defaultActionMap), m_BehaviorParameters, null);
m_ActionSpec = CombineActuatorActionSpecs(actuators);
if (!EditorApplication.isPlaying && m_ActionSpec.NumContinuousActions == 0
&& m_ActionSpec.BranchSizes == null
|| m_ActionSpec.BranchSizes.Length == 0)
{
FindNeededComponents();
var actuators = CreateActuatorsFromMap(m_InputAsset.FindActionMap(m_PlayerInput.defaultActionMap),
m_BehaviorParameters,
null,
InputActuatorEventContext.s_EditorContext);
m_ActionSpec = CombineActuatorActionSpecs(actuators);

}
#endif
return m_ActionSpec;
}
Expand Down Expand Up @@ -119,7 +130,8 @@ public override IActuator[] CreateActuators()
RegisterLayoutBuilder(inputActionMap, m_LayoutName);
m_Device = InputSystem.AddDevice(m_LayoutName);

m_Actuators = CreateActuatorsFromMap(inputActionMap, m_BehaviorParameters, m_Device);
var context = new InputActuatorEventContext(inputActionMap.actions.Count, m_Device);
m_Actuators = CreateActuatorsFromMap(inputActionMap, m_BehaviorParameters, m_Device, context);

UpdateDeviceBinding(m_BehaviorParameters.IsInHeuristicMode());
inputActionMap.Enable();
Expand All @@ -141,15 +153,16 @@ static ActionSpec CombineActuatorActionSpecs(IActuator[] actuators)

internal static IActuator[] CreateActuatorsFromMap(InputActionMap inputActionMap,
BehaviorParameters behaviorParameters,
InputDevice inputDevice)
InputDevice inputDevice,
InputActuatorEventContext context)
{
var actuators = new IActuator[inputActionMap.actions.Count];
for (var i = 0; i < inputActionMap.actions.Count; i++)
{
var action = inputActionMap.actions[i];
var actionLayout = InputSystem.LoadLayout(action.expectedControlType);
var adaptor = (IRLActionInputAdaptor)Activator.CreateInstance(controlTypeToAdaptorType[actionLayout.type]);
actuators[i] = new InputActionActuator(inputDevice, behaviorParameters, action, adaptor);
actuators[i] = new InputActionActuator(inputDevice, behaviorParameters, action, adaptor, context);

// Reasonably, the input system starts adding numbers after the first none numbered name
// is added. So for device ID of 0, we use the empty string in the path.
Expand All @@ -158,6 +171,7 @@ internal static IActuator[] CreateActuatorsFromMap(InputActionMap inputActionMap
action.interactions,
action.processors,
mlAgentsControlSchemeName);
action.bindingMask = InputBinding.MaskByGroup(mlAgentsControlSchemeName);
}
return actuators;
}
Expand Down Expand Up @@ -326,6 +340,43 @@ internal void CleanupActionAsset()
m_BehaviorParameters = null;
m_Device = null;
}

int m_ActuatorsWrittenToEvent;
NativeArray<byte> m_InputBufferForFrame;
InputEventPtr m_InputEventPtrForFrame;
public InputEventPtr GetEventForFrame()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
return new InputEventPtr();
}
#endif
if (m_ActuatorsWrittenToEvent % m_Actuators.Length == 0 || !m_InputEventPtrForFrame.valid)
{
m_ActuatorsWrittenToEvent = 0;
m_InputEventPtrForFrame = new InputEventPtr();
m_InputBufferForFrame = StateEvent.From(m_Device, out m_InputEventPtrForFrame);
}

return m_InputEventPtrForFrame;
}

public void EventProcessedInFrame()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
return;
}
#endif
m_ActuatorsWrittenToEvent++;
if (m_ActuatorsWrittenToEvent == m_Actuators.Length && m_InputEventPtrForFrame.valid)
{
InputSystem.QueueEvent(m_InputEventPtrForFrame);
m_InputBufferForFrame.Dispose();
}
}
}
}
#endif // MLA_INPUT_SYSTEM && UNITY_2019_4_OR_NEWER
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#if MLA_INPUT_SYSTEM && UNITY_2019_4_OR_NEWER
using System;
using Unity.Collections;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.LowLevel;
#if UNITY_EDITOR
using UnityEditor;
#endif

namespace Unity.MLAgents.Extensions.Input
{
/// <summary>
/// This interface is passed to InputActionActuators to allow them to write to InputEvents.
/// The way this interface should be used is to request the <see cref="InputEventPtr"/> by calling
/// <see cref="GetEventForFrame"/> then call <see cref="EventProcessedInFrame"/> before returning from
/// </summary>
public class InputActuatorEventContext : IDisposable
{

/// <summary>
/// The number of times to allow the use of an event before queuing it in the InputSystem.
/// </summary>
public readonly int NumTimesToProcess;
public readonly InputDevice InputDevice;
NativeArray<byte> m_EventBuffer;
InputEventPtr m_Ptr;
int m_Count;

#if UNITY_EDITOR
public static InputActuatorEventContext s_EditorContext = new InputActuatorEventContext();
#endif

public InputActuatorEventContext(int numTimesToProcess = 1, InputDevice device = null)
{
NumTimesToProcess = numTimesToProcess;
InputDevice = device;
m_Count = 0;
m_Ptr = new InputEventPtr();
m_EventBuffer = new NativeArray<byte>();
}

/// <summary>
/// Returns the <see cref="InputEventPtr"/> to write to for the current frame.
/// </summary>
/// <returns>The <see cref="InputEventPtr"/> to write to for the current frame.</returns>
public IDisposable GetEventForFrame(out InputEventPtr eventPtr)
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
eventPtr = new InputEventPtr();
}
#endif
if (m_Count % NumTimesToProcess == 0)
{
m_Count = 0;
m_EventBuffer = StateEvent.From(InputDevice, out m_Ptr);
}
eventPtr = m_Ptr;
return this;
}

public void Dispose()
{
#if UNITY_EDITOR
if (!EditorApplication.isPlaying)
{
return;
}
#endif
m_Count++;
if (m_Count == NumTimesToProcess && m_Ptr.valid)
{
InputSystem.QueueEvent(m_Ptr);
m_EventBuffer.Dispose();
}

}
}
}
#endif // MLA_INPUT_SYSTEM && UNITY_2019_4_OR_NEWER

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading