Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Question Observing properties of multiple objects to choose from

Discussion in 'ML-Agents' started by GeorgGrech, Mar 8, 2023.

  1. GeorgGrech

    GeorgGrech

    Joined:
    Nov 26, 2021
    Posts:
    6
    Good day,

    I'm making a project with Unity ML Agents and I'm not sure if I've set my observations correctly.

    In my project, an agent collects resources then sells them at its home base for points.
    upload_2023-3-8_18-3-5.png

    Before requesting a decision, the agent scans the area around it and gets info about the resources, including distances and type of resource.

    Using discrete actions I've managed to set the agent to be able to choose between going to base and choosing a resource from the list.
    Code (CSharp):
    1. public override void OnActionReceived(ActionBuffers actionBuffers)
    2.     {
    3.         int actionIndex = actionBuffers.DiscreteActions[0];
    4.  
    5.         if (actionIndex == 0) //0 means returns to base
    6.         {
    7.             Debug.Log("Return to base");
    8.             StartCoroutine(ReturnToBase());
    9.         }
    10.  
    11.  
    12.         else //1 or greater, choose to gather a resource
    13.         {
    14.             Debug.Log("Going to gather resource " + (actionIndex - 1) + ": " + resourcesTrackingList[actionIndex - 1].type);
    15.             StartCoroutine(GatherResource(resourcesTrackingList[actionIndex - 1].resourceObject.transform));
    16.         }
    17.     }
    However, I'm not quite sure about how to have the agent observe the properties of all the objects in the list and match them with the decisions it can take. Currently I'm observing the properties of all the objects in the list with a foreach loop in CollectObservations.

    Code (CSharp):
    1.     public override void CollectObservations(VectorSensor sensor)
    2.     {
    3.         try
    4.         {
    5.             if (resourcesTrackingList != null && resourcesTrackingList.Count > 0)
    6.             {
    7.                 foreach (ResourceData resourceData in resourcesTrackingList)
    8.                 {
    9.                     sensor.AddObservation(resourceData.distanceFromPlayer/50); //Normalize to 50 (limited range)
    10.                     sensor.AddObservation(resourceData.distanceFromBase/200); //Normalize to 200 (unlimited range)
    11.                     sensor.AddOneHotObservation((int)resourceData.type, resourceData.numOfTypes);
    12.                     sensor.AddObservation((float)resourceData.invAmountLeft/enemyPlayer.maxInventorySize);
    13.                 }
    14.             }
    15.  
    16.             sensor.AddObservation((float)enemyPlayer.inventoryAmountFree/ enemyPlayer.maxInventorySize); //Keep track of inventory
    17.         }
    18.  
    19.         catch
    20.         {
    21.             Debug.Log("Exception caught in observations");
    22.         }
    23.     }
    Does this make sense? If not, what would be a more ideal way to go about observing properties of multiple objects? Help would be majorly appreciated.

    Thanks!