コード例 #1
0
    // Returns a list of float defining the state of the agent
    public override List <float> CollectState()
    {
        List <float> state = new List <float>();

        // @note: we handle changing state size (i.e. more marbles) by applying state size to the brain based on the number of marbles

        // we get the bottomest marble only with negative velocity (i.e. the one that is going down!)
        // this is because we cannot change state size with the curriculum, so we cannot just add more marbles and check all of them
        // also, we are not interested in high marbles, after all
        // @note: we could check the two bottomest marbles if needed
        Marble riskyestMarble = marbles[0];

        if (!stateUseAllMarbles)
        {
            for (var mi = 1; mi < nMarbles; mi++) // Only the first nMarbles are considered
            {
                var marble = marbles[mi];
                var velOld = riskyestMarble.GetComponent <Rigidbody>().velocity.y;
                var velNew = marble.GetComponent <Rigidbody>().velocity.y;
                // TODO: cache RB into marble itself so we do not call GetComponent
                if (velNew < velOld)
                {
                    // going down-er!
                    riskyestMarble = marble;
                }
                else if (Math.Abs(velNew - velOld) < 0.01f)
                {
                    if (marble.transform.position.y < riskyestMarble.transform.position.y)
                    {
                        riskyestMarble = marble;
                    }
                }
            }
            foreach (var marble in marbles)
            {
                marble.GetComponentInChildren <MeshRenderer>().material.color = Color.white;
            }
            riskyestMarble.GetComponentInChildren <MeshRenderer>().material.color = Color.red;
        }

        for (var mi = 0; mi < nMarbles; mi++) // Only the first nMarbles are considered
        {
            var marble     = marbles[mi];
            var usedMarble = marble;
            if (!stateUseAllMarbles)
            {
                usedMarble = riskyestMarble;
            }
            // Marble Position (+3)
            // @note: normalized and relative to agent's position
            if (stateUseMarblePosVelXZ)
            {
                state.Add((usedMarble.transform.position.x - transform.position.x) / (gridSize / 2f));
            }
            if (stateUseMarblePosVelY)
            {
                state.Add((usedMarble.transform.position.y - transform.position.y) / (areaHeight));
            }
            if (stateUseMarblePosVelXZ)
            {
                state.Add((usedMarble.transform.position.z - transform.position.z) / (gridSize / 2f));
            }

            // TODO: marbles should have a MAX SPEED
            // Marble Speed (+3)
            // @note: normalized based on max velocity
            var marbleRB       = usedMarble.transform.GetComponent <Rigidbody>();
            var marbleVelocity = marbleRB.velocity;
            if (stateUseMarblePosVelXZ)
            {
                state.Add(Mathf.Clamp(marbleVelocity.x, -maxMarbleVelocity, maxMarbleVelocity) / maxMarbleVelocity);
            }
            if (stateUseMarblePosVelY)
            {
                state.Add(Mathf.Clamp(marbleVelocity.y, -maxMarbleVelocity, maxMarbleVelocity) / maxMarbleVelocity);
            }
            if (stateUseMarblePosVelXZ)
            {
                state.Add(Mathf.Clamp(marbleVelocity.z, -maxMarbleVelocity, maxMarbleVelocity) / maxMarbleVelocity);
            }

            // TODO: marbles should have a MAX angular velocity
            // Marble Angular Velocity (+3)
            var marbleAngularVelocity = marbleRB.angularVelocity;
            if (stateUseMarblePosVelXZ)
            {
                state.Add(Mathf.Clamp(marbleAngularVelocity.x, -maxMarbleVelocity, maxMarbleVelocity) /
                          maxMarbleVelocity);
            }
            if (stateUseMarblePosVelY)
            {
                state.Add(Mathf.Clamp(marbleAngularVelocity.y, -maxMarbleVelocity, maxMarbleVelocity) /
                          maxMarbleVelocity);
            }
            if (stateUseMarblePosVelXZ)
            {
                state.Add(Mathf.Clamp(marbleAngularVelocity.z, -maxMarbleVelocity, maxMarbleVelocity) /
                          maxMarbleVelocity);
            }

            if (!stateUseAllMarbles)
            {
                break;                      // Only one
            }
        }


        foreach (var block in blocks)
        {
            // Block trigger time (+1)
            if (stateUseBlockTriggerTime)
            {
                state.Add(block.CurrentTriggerTime);
            }

            // Block position (+2)
            if (stateUseBlockPos)
            {
                state.Add((block.transform.position.x - transform.position.x) / (gridSize / 2f));
                //state.Add((block.transform.position.y - transform.position.y) / (gridSize / 2f));
                state.Add((block.transform.position.z - transform.position.z) / (gridSize / 2f));
            }

            // Block rotation (+3)
            if (stateUseBlockRot)
            {
                state.Add(block.transform.localEulerAngles.x / blockRotationAngleLimit);
                state.Add(block.transform.localEulerAngles.y / blockRotationAngleLimit);
                state.Add(block.transform.localEulerAngles.z / blockRotationAngleLimit);
            }

            // Block velocity (+2)
            if (stateUseBlockVel)
            {
                // TODO: range -1,1
                //var blockRb = block.GetComponent<Rigidbody>();
                //var blockVel = blockRb.velocity;
                state.Add(Mathf.Clamp(block.speed.x, -maxBlockVelocity, maxBlockVelocity) / maxBlockVelocity);
                //state.Add(Mathf.Clamp(blockVel.y, -maxBlockVelocity, maxBlockVelocity) / maxBlockVelocity);
                state.Add(Mathf.Clamp(block.speed.z, -maxBlockVelocity, maxBlockVelocity) / maxBlockVelocity);
            }
        }

        if (verboseState)
        {
            string statesString = "State:";
            for (int i = 0; i < state.Count; i++)
            {
                statesString += " " + state[i] + "\n";
            }
            Debug.Log(statesString);
        }

        return(state);
    }