Reputation: 1
I'm training a rag doll to walk based on the WalkerAgent training from Unity and I changed a couple things around to better fit my purposes. Now every time any body part from the rag doll collides with the ground, agent is null, preventing any rewards from being applied.
I have double checked my code multiple times and it doesn't look like there are any problems. The project also appears to be correctly set up. The original error that sent me down this rabbit hole was
nullreferenceexception: Object reference not set to an instance of an objectUnity.MLAgentsExamples.ObjectContact.OnCollisionStay (UnityEngine.Collision col) (at Assets/Scripts/ObjectContact.cs:55)UnityEngine.Physics:OnSceneContact(PhysicsScene, IntPtr, Int32) (at /Users/bokken/build/output/unity/unity/Modules/Physics/ScriptBindings/PhysicsContact.bindings.cs:49)
I'm pretty sure everything is happening in the correct order and that the agent should be initialized before it is called.
As far as I can tell, these are the relevant portions of code.
From WalkerAgent (the main script):
public override void Initialize()
{
m_OrientationCube = GetComponentInChildren<OrientationCubeController>();
//Setup each body part
m_JdController = GetComponent<JointDriveController>();
m_JdController.SetupBodyPart(hips);
m_JdController.SetupBodyPart(spine);
m_JdController.SetupBodyPart(head);
m_JdController.SetupBodyPart(legrotateL);
m_JdController.SetupBodyPart(thighL);
m_JdController.SetupBodyPart(kneerotateL);
m_JdController.SetupBodyPart(shinL);
m_JdController.SetupBodyPart(footL);
m_JdController.SetupBodyPart(legrotateR);
m_JdController.SetupBodyPart(thighR);
m_JdController.SetupBodyPart(kneerotateR);
m_JdController.SetupBodyPart(shinR);
m_JdController.SetupBodyPart(footR);
m_JdController.SetupBodyPart(armrotateL);
m_JdController.SetupBodyPart(armL);
m_JdController.SetupBodyPart(forearmrotateL);
m_JdController.SetupBodyPart(forearmL);
m_JdController.SetupBodyPart(handL);
m_JdController.SetupBodyPart(armrotateR);
m_JdController.SetupBodyPart(armR);
m_JdController.SetupBodyPart(forearmrotateR);
m_JdController.SetupBodyPart(forearmR);
m_JdController.SetupBodyPart(handR);
}
From JointDriveController:
public void SetupBodyPart(Transform t)
{
var bp = new BodyPart
{
rb = t.GetComponent<Rigidbody>(),
joint = t.GetComponent<CharacterJoint>(),
startingPos = t.position,
startingRot = t.rotation
};
bp.rb.maxAngularVelocity = k_MaxAngularVelocity;
// Add & setup the ground contact script
bp.objectContact = t.GetComponent<ObjectContact>();
var agent = gameObject.GetComponent<Agent>();
if (agent == null)
{
agent = gameObject.AddComponent<Agent>();
}
bp.objectContact.agent = agent;
if (!bp.objectContact)
{
bp.objectContact = t.gameObject.AddComponent<ObjectContact>();
bp.objectContact.agent = gameObject.GetComponent<Agent>();
}
else
bp.objectContact.agent = gameObject.GetComponent<Agent>();
if (bp.objectContact.agent == null)
Debug.LogError($"Agent not found for {t.name}");
bp.thisJdController = this;
bodyPartsDict.Add(t, bp);
bodyPartsList.Add(bp);
}
From ObjectContact:
void OnCollisionEnter(Collision col)
{
if (agent == null)
{
Debug.LogError($"Agent is null on {gameObject.name} during OnCollisionEnter with {col.gameObject.name}");
return;
}
if (col.transform.CompareTag(k_Ground))
touchingGround = true;
if (col.transform.CompareTag(k_Wall))
touchingWall = true;
if (col.transform.CompareTag(k_Target))
{
touchingTarget = true;
agent.AddReward(targetReward);
}
}
void OnCollisionStay(Collision col)
{
if (col.transform.CompareTag(k_Ground))
agent.AddReward(groundContactPenalty);
if (col.transform.CompareTag(k_Wall))
agent.AddReward(wallContactPenalty);
Debug.Log($"OnCollisionStay called for {gameObject.name} with {col.gameObject.name}");
if (agent == null)
{
Debug.LogError("Agent is null during OnCollisionStay");
return;
}
}
Upvotes: 0
Views: 45