您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
181 行
4.5 KiB
181 行
4.5 KiB
using System;
|
|
using UnityEngine;
|
|
using MLAgents;
|
|
using MLAgents.Policies;
|
|
|
|
public class AgentSoccer : Agent
|
|
{
|
|
// Note that that the detectable tags are different for the blue and purple teams. The order is
|
|
// * ball
|
|
// * own goal
|
|
// * opposing goal
|
|
// * wall
|
|
// * own teammate
|
|
// * opposing player
|
|
public enum Team
|
|
{
|
|
Blue = 0,
|
|
Purple = 1
|
|
}
|
|
|
|
[HideInInspector]
|
|
public Team team;
|
|
float m_KickPower;
|
|
int m_PlayerIndex;
|
|
public SoccerFieldArea area;
|
|
|
|
[HideInInspector]
|
|
public Rigidbody agentRb;
|
|
SoccerSettings m_SoccerSettings;
|
|
BehaviorParameters m_BehaviorParameters;
|
|
Vector3 m_Transform;
|
|
|
|
public override void Initialize()
|
|
{
|
|
m_BehaviorParameters = gameObject.GetComponent<BehaviorParameters>();
|
|
if (m_BehaviorParameters.TeamId == (int)Team.Blue)
|
|
{
|
|
team = Team.Blue;
|
|
m_Transform = new Vector3(transform.position.x - 4f, .5f, transform.position.z);
|
|
}
|
|
else
|
|
{
|
|
team = Team.Purple;
|
|
m_Transform = new Vector3(transform.position.x + 4f, .5f, transform.position.z);
|
|
}
|
|
m_SoccerSettings = FindObjectOfType<SoccerSettings>();
|
|
agentRb = GetComponent<Rigidbody>();
|
|
agentRb.maxAngularVelocity = 500;
|
|
|
|
var playerState = new PlayerState
|
|
{
|
|
agentRb = agentRb,
|
|
startingPos = transform.position,
|
|
agentScript = this,
|
|
};
|
|
area.playerStates.Add(playerState);
|
|
m_PlayerIndex = area.playerStates.IndexOf(playerState);
|
|
playerState.playerIndex = m_PlayerIndex;
|
|
}
|
|
|
|
public void MoveAgent(float[] act)
|
|
{
|
|
var dirToGo = Vector3.zero;
|
|
var rotateDir = Vector3.zero;
|
|
|
|
m_KickPower = 0f;
|
|
|
|
var forwardAxis = (int)act[0];
|
|
var rightAxis = (int)act[1];
|
|
var rotateAxis = (int)act[2];
|
|
|
|
switch (forwardAxis)
|
|
{
|
|
case 1:
|
|
dirToGo = transform.forward * 1f;
|
|
m_KickPower = 1f;
|
|
break;
|
|
case 2:
|
|
dirToGo = transform.forward * -1f;
|
|
break;
|
|
}
|
|
|
|
switch (rightAxis)
|
|
{
|
|
case 1:
|
|
dirToGo = transform.right * 0.3f;
|
|
break;
|
|
case 2:
|
|
dirToGo = transform.right * -0.3f;
|
|
break;
|
|
}
|
|
|
|
switch (rotateAxis)
|
|
{
|
|
case 1:
|
|
rotateDir = transform.up * -1f;
|
|
break;
|
|
case 2:
|
|
rotateDir = transform.up * 1f;
|
|
break;
|
|
}
|
|
|
|
transform.Rotate(rotateDir, Time.deltaTime * 100f);
|
|
agentRb.AddForce(dirToGo * m_SoccerSettings.agentRunSpeed,
|
|
ForceMode.VelocityChange);
|
|
}
|
|
|
|
public override void OnActionReceived(float[] vectorAction)
|
|
{
|
|
// Existential penalty for strikers.
|
|
AddReward(-1f / 3000f);
|
|
MoveAgent(vectorAction);
|
|
}
|
|
|
|
public override float[] Heuristic()
|
|
{
|
|
var action = new float[3];
|
|
//forward
|
|
if (Input.GetKey(KeyCode.W))
|
|
{
|
|
action[0] = 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.S))
|
|
{
|
|
action[0] = 2f;
|
|
}
|
|
//rotate
|
|
if (Input.GetKey(KeyCode.A))
|
|
{
|
|
action[2] = 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.D))
|
|
{
|
|
action[2] = 2f;
|
|
}
|
|
//right
|
|
if (Input.GetKey(KeyCode.E))
|
|
{
|
|
action[1] = 1f;
|
|
}
|
|
if (Input.GetKey(KeyCode.Q))
|
|
{
|
|
action[1] = 2f;
|
|
}
|
|
return action;
|
|
}
|
|
/// <summary>
|
|
/// Used to provide a "kick" to the ball.
|
|
/// </summary>
|
|
void OnCollisionEnter(Collision c)
|
|
{
|
|
var force = 2000f * m_KickPower;
|
|
if (c.gameObject.CompareTag("ball"))
|
|
{
|
|
var dir = c.contacts[0].point - transform.position;
|
|
dir = dir.normalized;
|
|
c.gameObject.GetComponent<Rigidbody>().AddForce(dir * force);
|
|
}
|
|
}
|
|
|
|
public override void OnEpisodeBegin()
|
|
{
|
|
if (team == Team.Purple)
|
|
{
|
|
transform.rotation = Quaternion.Euler(0f, -90f, 0f);
|
|
}
|
|
else
|
|
{
|
|
transform.rotation = Quaternion.Euler(0f, 90f, 0f);
|
|
}
|
|
transform.position = m_Transform;
|
|
agentRb.velocity = Vector3.zero;
|
|
agentRb.angularVelocity = Vector3.zero;
|
|
SetResetParameters();
|
|
}
|
|
|
|
public void SetResetParameters()
|
|
{
|
|
area.ResetBall();
|
|
}
|
|
}
|