ppo-Pyramids-Training
/
Project
/Assets
/ML-Agents
/Examples
/PushBlockWithInput
/Scripts
/PushBlockWithInputPlayerController.cs
using Unity.MLAgents.Extensions.Input; | |
using UnityEngine; | |
using UnityEngine.InputSystem; | |
/// <summary> | |
/// This class handles the input for the PushBlock Cube character in the PushBlock scene. | |
/// Note that the only ML-Agents code here is the implementation of the <see cref="IInputActionAssetProvider"/>. | |
/// The <see cref="InputActuatorComponent"/> looks for a component that implements that interface in order to | |
/// rebind actions to virtual controllers when training agents or running inference. This means that you can | |
/// keep your input handling code separate from ML-Agents, and have your agent's action space defined by the | |
/// actions defined in your project's <see cref="GetInputActionAsset"/>. | |
/// | |
/// If you don't implement <see cref="IInputActionAssetProvider"/> the <see cref="InputActuatorComponent"/> will | |
/// look for a <see cref="PlayerInput"/> component on the GameObject it live on. It will rebind the actions of that | |
/// instance of the asset. | |
/// | |
/// It is important to note that if you have multiple components on the same GameObject handling input, you will | |
/// need to share the instance of the generated C# <see cref="IInputActionCollection2"/> (named <see cref="m_PushBlockActions"/> | |
/// here) in order to ensure that all of your actions are bound correctly for ml-agents training and inference. | |
/// </summary> | |
public class PushBlockWithInputPlayerController : MonoBehaviour, IInputActionAssetProvider | |
{ | |
PushBlockWithInputSettings m_PushBlockSettings; | |
public float JumpTime = 0.5f; | |
float m_JumpTimeRemaining; | |
Rigidbody m_PlayerRb; //cached on initialization | |
PushBlockActions m_PushBlockActions; | |
float m_JumpCoolDownStart; | |
void Awake() | |
{ | |
m_PushBlockSettings = FindObjectOfType<PushBlockWithInputSettings>(); | |
LazyInitializeActions(); | |
// Cache the agent rigidbody | |
m_PlayerRb = GetComponent<Rigidbody>(); | |
} | |
void LazyInitializeActions() | |
{ | |
if (m_PushBlockActions != null) | |
{ | |
return; | |
} | |
m_PushBlockActions = new PushBlockActions(); | |
m_PushBlockActions.Enable(); | |
// You can listen to C# events. | |
m_PushBlockActions.Movement.jump.performed += JumpOnperformed; | |
} | |
void JumpOnperformed(InputAction.CallbackContext callbackContext) | |
{ | |
InnerJump(gameObject.transform); | |
} | |
void FixedUpdate() | |
{ | |
// Or you can poll the action itself like we do here. | |
InnerMove(gameObject.transform, m_PushBlockActions.Movement.movement.ReadValue<Vector2>()); | |
if (m_JumpTimeRemaining < 0) | |
{ | |
m_PlayerRb.AddForce(-transform.up * (m_PushBlockSettings.agentJumpForce * 3), ForceMode.Acceleration); | |
} | |
m_JumpTimeRemaining -= Time.fixedDeltaTime; | |
} | |
void InnerJump(Transform t) | |
{ | |
if (Time.realtimeSinceStartup - m_JumpCoolDownStart > m_PushBlockSettings.agentJumpCoolDown) | |
{ | |
m_JumpTimeRemaining = JumpTime; | |
m_PlayerRb.AddForce(t.up * m_PushBlockSettings.agentJumpForce, ForceMode.VelocityChange); | |
m_JumpCoolDownStart = Time.realtimeSinceStartup; | |
} | |
} | |
void InnerMove(Transform t, Vector2 v) | |
{ | |
var forward = CreateForwardVector(v); | |
var up = CreateUpVector(v); | |
var dirToGo = t.forward * forward; | |
var rotateDir = t.up * up; | |
t.Rotate(rotateDir, Time.deltaTime * 200f); | |
m_PlayerRb.AddForce(dirToGo * m_PushBlockSettings.agentRunSpeed, | |
ForceMode.VelocityChange); | |
} | |
static float CreateUpVector(Vector2 move) | |
{ | |
return Mathf.Abs(move.x) > Mathf.Abs(move.y) ? move.x : 0f; | |
} | |
static float CreateForwardVector(Vector2 move) | |
{ | |
return Mathf.Abs(move.y) > Mathf.Abs(move.x) ? move.y : 0f; | |
} | |
/// <summary> | |
/// This is the implementation of the <see cref="IInputActionAssetProvider"/> for this class. We need | |
/// both the <see cref="GetInputActionAsset"/> and the <see cref="IInputActionCollection2"/> if you are | |
/// listening to C# events, Unity Events, or receiving Messages from the Input System Package as those callbacks | |
/// are set up through the generated <see cref="IInputActionCollection2"/>. | |
/// </summary> | |
/// <returns></returns> | |
public (InputActionAsset, IInputActionCollection2) GetInputActionAsset() | |
{ | |
LazyInitializeActions(); | |
return (m_PushBlockActions.asset, m_PushBlockActions); | |
} | |
} | |