Matt Clarke
Matt Clarke

Reputation: 1

Agent is null when any part of my game object collides

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

Answers (0)

Related Questions