Unity 机器学习代理工具包 (ML-Agents) 是一个开源项目,它使游戏和模拟能够作为训练智能代理的环境。
您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 

407 行
14 KiB

//Standardized movement controller for the Agent Cube
using System;
using Unity.Mathematics;
using UnityEngine;
namespace MLAgents
{
public class AgentCubeMovement : MonoBehaviour
{
//ONLY ALLOW SCRIPTED MOVEMENT VIA ML-AGENTS OR OTHER HEURISTIC SCRIPTS
[Header("INPUT")]
public bool allowHumanInput = true;
// public DodgeBallAgentInput input;
[Header("RIGIDBODY")] public float maxAngularVel = 50;
[Header("RUNNING")] public ForceMode runningForceMode = ForceMode.Impulse;
//speed agent can run if grounded
public float agentRunSpeed = 10;
public float agentTerminalVel = 20;
//speed agent can run if not grounded
public float agentRunInAirSpeed = 7f;
[Header("STRAFE")]
public float strafeSpeed = 10;
public float strafeCoolDownDuration = .2f;
public float strafeCoolDownTimer;
public ForceMode strafeForceMode = ForceMode.Impulse;
[Header("DASH")]
public float dashBoostForce = 20f;
public ForceMode dashForceMode = ForceMode.Impulse;
public bool dashPressed;
public float dashCoolDownDuration = .2f;
public float dashCoolDownTimer;
[Header("IDLE")]
//coefficient used to dampen velocity when idle
//the purpose of this is to fine tune agent drag
//...and prevent the agent sliding around while grounded
//0 means it will instantly stop when grounded
//1 means no drag will be applied
public float agentIdleDragVelCoeff = .9f;
[Header("GROUND POUND")] public bool UseGroundPound;
public ForceMode groundPoundForceMode = ForceMode.Impulse;
public float groundPoundForce = 35f;
[Header("SPIN ATTACK")]
public float spinAttackSpeed = 20f;
private bool spinAttack;
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 };
[Header("BODY ROTATION")] public bool UseMouseRotation = true;
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationX = 0F;
float rotationY = 0F;
Quaternion originalRotation;
[Header("BODY ROTATION")]
public bool MatchCameraRotation;
//body rotation speed
public bool invertRotationIfWalkingBackwards = true;
public float agentRotationSpeed = 35f;
private Vector2 m_Rotation;
[Header("JUMPING")] public bool canJump = true;
//upward jump velocity magnitude
public float agentJumpVelocity = 15f;
[Header("FALLING FORCE")]
//force applied to agent while falling
public float agentFallingSpeed = 50f;
[Header("ANIMATE MESH")] public bool AnimateBodyMesh;
public AnimationCurve walkingBounceCurve;
public float walkingAnimScale = 1;
public Transform bodyMesh;
private float m_animateBodyMeshCurveTimer;
public Camera cam;
private float lookDir;
private Rigidbody rb;
public AgentCubeGroundCheck groundCheck;
private float inputH;
private float inputV;
private bool jump;
void Awake()
{
rb = GetComponent<Rigidbody>();
groundCheck = GetComponent<AgentCubeGroundCheck>();
rb.maxAngularVelocity = maxAngularVel;
originalRotation = transform.localRotation;
}
void Update()
{
if (!allowHumanInput)
{
return;
}
//FORWARD MOVEMENT
inputV = Input.GetAxisRaw("Vertical");
inputH = Input.GetAxisRaw("Horizontal");
spinAttack = Input.GetKey(KeyCode.H);
dashPressed = Input.GetKeyDown(KeyCode.K);
jump = Input.GetKeyDown(KeyCode.Space);
var camForward = cam.transform.forward;
camForward.y = 0;
var camRight = cam.transform.right;
if (canJump && Input.GetKeyDown(KeyCode.Space))
{
if (groundCheck)
{
if (groundCheck.isGrounded)
{
Jump();
}
else if (UseGroundPound)
{
rb.AddForce(Vector3.down * groundPoundForce, groundPoundForceMode);
}
}
}
if (dashPressed)
{
// dashPressed = false;
// rb.AddForce(rb.transform.forward * dashBoostForce, dashForceMode);
rb.AddTorque(rb.transform.right * dashBoostForce, dashForceMode);
print("dashPressed");
}
}
public void RotateBody(float rotateAxis, float forwardAxis)
{
// var walkingBackwardsCoeff = 1;
// if (invertRotationIfWalkingBackwards && forwardAxis < 0)
// {
// walkingBackwardsCoeff = -1;
// }
// var scaledRotateSpeed = agentRotationSpeed * Time.fixedDeltaTime;
// var amount = Quaternion.Euler(0, rotateAxis * walkingBackwardsCoeff , 0);
// var amount = Quaternion.Euler(0, rotateAxis * agentRotationSpeed * walkingBackwardsCoeff * Time.fixedDeltaTime, 0);
var amount = Quaternion.Euler(0, rotateAxis * agentRotationSpeed * Time.fixedDeltaTime, 0);
rb.rotation *= amount;
// rb.MoveRotation(rb.rotation * amount);
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
public void Look(float xRot = 0, float yRot = 0)
{
// Read the mouse input axis
rotationX += xRot * sensitivityX;
rotationY += yRot * sensitivityY;
// rotationX += xRot * sensitivityX * Time.deltaTime;
// rotationY += yRot * sensitivityY * Time.deltaTime;
// rotationX += Input.GetAxis("Mouse X") * sensitivityX;
// rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
rotationX = ClampAngle(rotationX, minimumX, maximumX);
rotationY = ClampAngle(rotationY, minimumY, maximumY);
Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis(rotationY, -Vector3.right);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
// print("look");
}
public bool applyStandingForce = false;
public float standingForce = 10;
public ForceMode standingForceForceMode;
public float standingForcePositionOffset = .5f;
void FixedUpdate()
{
strafeCoolDownTimer += Time.fixedDeltaTime;
dashCoolDownTimer += Time.fixedDeltaTime;
if (groundCheck && !groundCheck.isGrounded)
{
AddFallingForce(rb);
// print("AddFallingForce");
}
if (!allowHumanInput)
{
return;
}
if (UseMouseRotation)
{
if (axes == RotationAxes.MouseXAndY)
{
Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
Quaternion yQuaternion = Quaternion.AngleAxis(rotationY, -Vector3.right);
transform.localRotation = originalRotation * xQuaternion * yQuaternion;
}
else if (axes == RotationAxes.MouseX)
{
// rotationX += Input.GetAxis("Mouse X") * sensitivityX;
// rotationX = ClampAngle(rotationX, minimumX, maximumX);
Quaternion xQuaternion = Quaternion.AngleAxis(rotationX, Vector3.up);
transform.localRotation = originalRotation * xQuaternion;
}
// else
// {
// // rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
// // rotationY = ClampAngle(rotationY, minimumY, maximumY);
//
// Quaternion yQuaternion = Quaternion.AngleAxis(-rotationY, Vector3.right);
// transform.localRotation = originalRotation * yQuaternion;
// }
}
if (applyStandingForce)
{
//STANDING FORCES
rb.AddForceAtPosition(Vector3.up * standingForce, transform.TransformPoint(Vector3.up * standingForcePositionOffset),
standingForceForceMode);
rb.AddForceAtPosition(-Vector3.up * standingForce, transform.TransformPoint(-Vector3.up * standingForcePositionOffset),
standingForceForceMode);
}
if (spinAttack)
{
// rb.AddTorque(Vector3.up * spinAttackSpeed);
rb.angularVelocity = Vector3.up * spinAttackSpeed;
}
var moveDir = transform.TransformDirection(new Vector3(inputH, 0, inputV));
if (groundCheck.isGrounded)
{
RunOnGround(moveDir);
}
// else
// {
// RunInAir(dir.normalized);
// }
if (inputH == 0 && inputV == 0)
{
// if (groundCheck && groundCheck.isGrounded && !dashPressed)
if (groundCheck && groundCheck.isGrounded)
{
AddIdleDrag(rb);
// print("AddIdleDrag");
}
}
}
public void Jump()
{
Vector3 velToUse = rb.velocity;
velToUse.y = agentJumpVelocity;
rb.velocity = velToUse;
}
public void RotateBody(Rigidbody rb, Vector3 rotationAxis)
{
rb.MoveRotation(rb.rotation * Quaternion.AngleAxis(agentRotationSpeed, rotationAxis));
}
public void Strafe(Vector3 dir)
{
if (dir != Vector3.zero && strafeCoolDownTimer > strafeCoolDownDuration)
{
rb.velocity = Vector3.zero;
rb.AddForce(dir.normalized * strafeSpeed, strafeForceMode);
strafeCoolDownTimer = 0;
}
}
public void Dash(Vector3 dir)
{
if (dir != Vector3.zero && dashCoolDownTimer > dashCoolDownDuration)
{
rb.velocity = Vector3.zero;
rb.AddForce(dir.normalized * dashBoostForce, dashForceMode);
dashCoolDownTimer = 0;
}
}
public void RotateTowards(Vector3 dir, float maxRotationRate = 1)
{
if (dir != Vector3.zero)
{
var rot = Quaternion.LookRotation(dir);
var smoothedRot = Quaternion.RotateTowards(rb.rotation, rot, maxRotationRate * Time.deltaTime);
rb.MoveRotation(smoothedRot);
// print($"rot {gameObject.name} {dir.normalized}");
}
}
public void RunOnGround(Vector3 dir)
{
//ADD FORCE
var vel = rb.velocity.magnitude;
float adjustedSpeed = Mathf.Clamp(agentRunSpeed - vel, 0, agentTerminalVel);
rb.AddForce(dir * adjustedSpeed, runningForceMode);
//ANIMATE MESH
if (dir == Vector3.zero)
{
if (AnimateBodyMesh)
{
bodyMesh.localPosition = Vector3.zero;
}
}
else
{
if (AnimateBodyMesh)
{
bodyMesh.localPosition = Vector3.zero +
Vector3.up * walkingAnimScale * walkingBounceCurve.Evaluate(
m_animateBodyMeshCurveTimer);
m_animateBodyMeshCurveTimer += Time.fixedDeltaTime;
}
}
}
public void RunOnGround(Rigidbody rb, Vector3 dir)
{
print(dir);
if (dir == Vector3.zero)
{
if (AnimateBodyMesh)
{
bodyMesh.localPosition = Vector3.zero;
}
}
else
{
var vel = rb.velocity.magnitude;
float adjustedSpeed = Mathf.Clamp(agentRunSpeed - vel, 0, agentTerminalVel);
// rb.AddForce(dir.normalized * adjustedSpeed, runningForceMode);
rb.AddForce(dir * adjustedSpeed, runningForceMode);
if (AnimateBodyMesh)
{
bodyMesh.localPosition = Vector3.zero +
Vector3.up * walkingAnimScale * walkingBounceCurve.Evaluate(
m_animateBodyMeshCurveTimer);
m_animateBodyMeshCurveTimer += Time.fixedDeltaTime;
}
// rb.AddForceAtPosition(dir.normalized * adjustedSpeed,transform.TransformPoint(Vector3.forward * standingForcePositionOffset),
// runningForceMode);
}
}
public void RunInAir(Rigidbody rb, Vector3 dir)
{
var vel = rb.velocity.magnitude;
float adjustedSpeed = Mathf.Clamp(agentRunInAirSpeed - vel, 0, agentTerminalVel);
rb.AddForce(dir.normalized * adjustedSpeed,
runningForceMode);
}
public void AddIdleDrag(Rigidbody rb)
{
rb.velocity *= agentIdleDragVelCoeff;
}
public void AddFallingForce(Rigidbody rb)
{
rb.AddForce(
Vector3.down * agentFallingSpeed, ForceMode.Acceleration);
}
}
}