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

168 行
5.7 KiB

using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
namespace MLAgents
{
/// <summary>
/// Used to store relevant information for acting and learning for each body part in agent.
/// </summary>
[System.Serializable]
public class ArticulationBodyPart
{
public ArticulationBody arb;
public Transform t;
[HideInInspector] public Vector3 startingPos;
[HideInInspector] public Quaternion startingRot;
[Header("Ground & Target Contact")][Space(10)]
public GroundContact groundContact;
public TargetContact targetContact;
[FormerlySerializedAs("thisJDController")]
[HideInInspector] public ArticulatedJointDriveController thisJdController;
[Header("Current Joint Settings")][Space(10)]
public Vector3 currentEularJointRotation;
[HideInInspector] public float currentStrength;
public float currentXNormalizedRot;
public float currentYNormalizedRot;
public float currentZNormalizedRot;
/// <summary>
/// Apply torque according to defined goal `x, y, z` angle and force `strength`.
/// </summary>
public void SetJointTargetRotation(float x, float y, float z)
{
x = (x + 1f) * 0.5f;
y = (y + 1f) * 0.5f;
z = (z + 1f) * 0.5f;
var xDrive = arb.xDrive;
var yDrive = arb.yDrive;
var zDrive = arb.zDrive;
var xRot = Mathf.Lerp(xDrive.lowerLimit, xDrive.upperLimit, x);
var yRot = Mathf.Lerp(yDrive.lowerLimit, yDrive.upperLimit, y);
var zRot = Mathf.Lerp(zDrive.lowerLimit, zDrive.upperLimit, z);
currentXNormalizedRot =
Mathf.InverseLerp(xDrive.lowerLimit, xDrive.upperLimit, xRot);
currentYNormalizedRot = Mathf.InverseLerp(yDrive.lowerLimit, yDrive.upperLimit, yRot);
currentZNormalizedRot = Mathf.InverseLerp(zDrive.lowerLimit, zDrive.upperLimit, zRot);
xDrive.target = xRot; yDrive.target = yRot; zDrive.target = zRot;
arb.xDrive = xDrive; arb.yDrive = yDrive; arb.zDrive = zDrive;
currentEularJointRotation = new Vector3(xRot, yRot, zRot);
}
public void SetJointStrength(float strength)
{
var xDrive = arb.xDrive;
var yDrive = arb.yDrive;
var zDrive = arb.zDrive;
var rawVal = (strength + 1f) * 0.5f * thisJdController.maxJointForceLimit;
xDrive.stiffness = yDrive.stiffness = zDrive.stiffness = thisJdController.maxJointSpring;
xDrive.damping = yDrive.damping = zDrive.damping = thisJdController.jointDampen;
xDrive.forceLimit = yDrive.forceLimit = zDrive.forceLimit = rawVal;
arb.xDrive = xDrive;
arb.yDrive = yDrive;
arb.zDrive = zDrive;
currentStrength = rawVal;
}
}
public class ArticulatedJointDriveController : MonoBehaviour
{
[Header("Joint Drive Settings")][Space(10)]
public float maxJointSpring;
public float jointDampen;
public float maxJointForceLimit;
float m_FacingDot;
[HideInInspector] public Dictionary<Transform, ArticulationBodyPart> bodyPartsDict = new Dictionary<Transform, ArticulationBodyPart>();
[HideInInspector] public List<ArticulationBodyPart> bodyPartsList = new List<ArticulationBodyPart>();
/// <summary>
/// Reset BodyPart list and dictionary.
/// </summary>
public void Reset()
{
bodyPartsDict.Clear();
bodyPartsList.Clear();
}
/// <summary>
/// Create BodyPart object and add it to dictionary.
/// </summary>
public void SetupBodyPart(Transform t)
{
// Either parent(in case of legs) or game object itself(in case of body) must have ArticulationBody
var arb = t.GetComponent<ArticulationBody>();
if (arb == null)
arb = t.parent.GetComponent<ArticulationBody>();
var bp = new ArticulationBodyPart()
{
arb = arb,
t = t,
startingPos = t.position,
startingRot = t.rotation
};
// Add & setup the ground contact script
bp.groundContact = t.GetComponent<GroundContact>();
if (!bp.groundContact)
{
bp.groundContact = t.gameObject.AddComponent<GroundContact>();
bp.groundContact.agent = gameObject.GetComponent<Agent>();
}
else
{
bp.groundContact.agent = gameObject.GetComponent<Agent>();
}
// Add & setup the target contact script
bp.targetContact = t.GetComponent<TargetContact>();
if (!bp.targetContact)
{
bp.targetContact = t.gameObject.AddComponent<TargetContact>();
}
bp.thisJdController = this;
bodyPartsDict.Add(t, bp);
bodyPartsList.Add(bp);
}
public static Transform FindBodyPartByName(Transform rootBody, string bodyPartName)
{
Queue<Transform> queue = new Queue<Transform>();
queue.Enqueue(rootBody);
while (queue.Count > 0)
{
Transform child = queue.Dequeue();
if (child.name == bodyPartName)
return child;
foreach(Transform t in child)
queue.Enqueue(t);
}
return null;
}
}
}