---
# System prepended metadata

title: 鬼抓人

---


- [x] 新的訓練場地
- [x] 鬼的行動(移動和抓到目標後的處理)
- [x] 物體位置重置
- [x] 搞懂ray perception sensor 3d 怎麼寫進去程式碼裡
- [x] 開始寫觀察
- [x] 開始寫利益
- [x] 開始訓練

8/28目標
鬼的移動，訓練場地(目標會重置)，Target重生於4個點(+-8，0.5，+-8)，鬼重生(0，0.5，0)
==>鬼抓到目標整體重置
搞懂ray perception sensor 3d的用法
==>書寫觀察

8/29目標
開始寫利益
訓練和調整

8/30
訓練好的模型放進大地圖
觀察和修改


![](https://hackmd.io/_uploads/ryw09wh63.png)

Ray Perception Sensor
https://www.cnblogs.com/gentlesunshine/p/12790103.html
https://forum.unity.com/threads/how-to-create-these-perception-rays.816789/
https://juejin.cn/post/7111119260553838629
https://www.immersivelimit.com/tutorials/unity-ml-agents-penguins
https://www.oreilly.com/library/view/practical-simulations-for/9781492089919/ch04.html




目前問題: RAY有碰到Target但沒有往他走。
1.可能是訓練的次數不夠
2.射線的目標沒有讀取(因為訓練不夠還不知道Target這個物體對他有好處)
需要加上對靠近牆壁的負利益




外圍不放入Wall的Tag裡，射線長度可以拉長，當足夠靠近牆壁給予不好的評分

一次訓練追目標和避開牆壁
分開訓練，先追目標(得到座標位置)，在用前面的模型去訓練避開牆壁

先測試射線有沒有用處(拿走座標)

碰到的得分應該寫外面，推測(SetReward(-1f / MaxStep);可能會執行不到)




https://forum.unity.com/threads/how-to-check-ray-perception-sensor-3d.1420445/
```
private void checkRayCast()
{
        RayPerceptionSensorComponent3D m_rayPerceptionSensorComponent3D = GetComponent<RayPerceptionSensorComponent3D>();
 
        var rayOutputs = RayPerceptionSensor.Perceive(m_rayPerceptionSensorComponent3D.GetRayPerceptionInput()).RayOutputs;
        int lengthOfRayOutputs = rayOutputs.Length;
 
        // Alternating Ray Order: it gives an order of
        // (0, -delta, delta, -2delta, 2delta, ..., -ndelta, ndelta)
        // index 0 indicates the center of raycasts
        for (int i = 0; i < lengthOfRayOutputs; i++)
        {
            GameObject goHit = rayOutputs[i].HitGameObject;
            if (goHit != null)
            {
                var rayDirection = rayOutputs[i].EndPositionWorld - rayOutputs[i].StartPositionWorld;
                var scaledRayLength = rayDirection.magnitude;
                float rayHitDistance = rayOutputs[i].HitFraction * scaledRayLength;
 
                // Print info:
                string dispStr = "";
                dispStr = dispStr + "__RayPerceptionSensor - HitInfo__:\r\n";
                dispStr = dispStr + "GameObject name: " + goHit.name + "\r\n";
                dispStr = dispStr + "Hit distance of Ray: " + rayHitDistance + "\r\n";
                dispStr = dispStr + "GameObject tag: " + goHit.tag + "\r\n";
                Debug.Log(dispStr);
            }
        }
}
```



https://forum.unity.com/threads/problem-on-collectobservations-of-agents-for-learning-to-form-the-formation-of-uavs.1449667/#post-9085933
https://forum.unity.com/threads/how-to-check-ray-perception-sensor-3d.1420445/#post-8940981
https://forum.unity.com/threads/ray-perception-sensor-3d-vs-raycast.1456792/
https://docs.unity3d.com/Packages/com.unity.ml-agents@1.0/api/Unity.MLAgents.Sensors.RayPerceptionSensorComponent3D.html



座標和Ray Perception Sensor 3D 可以同時存在(問題點是CollectObservations裡面就會需要寫Ray Perception Sensor 的射線資訊
chat給的
```
public override void CollectObservations(VectorSensor sensor)
{
    // 使用 Ray Perception Sensor 3D 感知物體
    RayPerceptionSensorComponent3D raySensor = GetComponent<RayPerceptionSensorComponent3D>();
    float[] rayAngles = raySensor.GetRayAngles();
    float[] rayDistances;
    string[] detectableObjects = raySensor.GetDetectableObjects();

    // 觀察每個射線的距離
    rayDistances = raySensor.Perceive(raySensor.MaxRayDegrees, rayAngles, detectableObjects, 0f, 0f);

    // 將距離觀察添加到 VectorSensor
    foreach (float distance in rayDistances)
    {
        sensor.AddObservation(distance);
    }

    // 也可以添加其他觀察，例如座標、速度等
    sensor.AddObservation(target.localPosition);
    sensor.AddObservation(transform.localPosition);
    sensor.AddObservation(AgentRb.velocity);
}
```

結合別人的checkray
```
public override void CollectObservations(VectorSensor sensor)
    {
        // 使用 Ray Perception Sensor 3D 感知物體
        RayPerceptionSensorComponent3D raySensor = GetComponent<RayPerceptionSensorComponent3D>();
        RayPerceptionInput input = raySensor.GetRayPerceptionInput();
        // 調用 checkRayCast 函數來處理射線感知的結果
        checkRayCast(input);
        //座標
        sensor.AddObservation(target.localPosition);
        sensor.AddObservation(transform.localPosition);
        sensor.AddObservation(AgentRb.velocity);
    }

    private void checkRayCast(RayPerceptionInput input)
    {
        RayPerceptionOutput rayOutput = RayPerceptionSensor.Perceive(input);
        int lengthOfRayOutputs = rayOutput.RayOutputs.Length;

        // 處理射線感知結果
        for (int i = 0; i < lengthOfRayOutputs; i++)
        {
            GameObject goHit = rayOutput.RayOutputs[i].HitGameObject;
            if (goHit != null)
            {
                var rayDirection = rayOutput.RayOutputs[i].EndPositionWorld - rayOutput.RayOutputs[i].StartPositionWorld;
                var scaledRayLength = rayDirection.magnitude;
                float rayHitDistance = rayOutput.RayOutputs[i].HitFraction * scaledRayLength;

                // 打印信息或者进行其他处理
                string dispStr = "";
                dispStr = dispStr + "__RayPerceptionSensor - HitInfo__:\r\n";
                dispStr = dispStr + "GameObject name: " + goHit.name + "\r\n";
                dispStr = dispStr + "Hit distance of Ray: " + rayHitDistance + "\r\n";
                dispStr = dispStr + "GameObject tag: " + goHit.tag + "\r\n";
                Debug.Log(dispStr);
            }
        }
    }
```

![](https://hackmd.io/_uploads/r1ljnI5u03.png)



Agent 射線 1.碰到牆壁(Wall) 2.碰到目標(Target) 3.沒碰到東西
依距離給予利益
1?->1距離要多少給負的利益，距離要分幾次(例如: 太近給高的負利益，遠一點給低的負利益)
2?->2正的利益要給多少才會最好，讓Agent不會因為目標太靠近牆壁並因為牆壁的利益而不往目標走
3?->3要不要給利益



(先用座標訓練抓位子，後面加上RAY去訓練避開牆壁)



==訓練重點
==
地圖大小會影響訓練的成效，地圖變大次數就需要增加許多，次數若沒變利益會很低





![](https://hackmd.io/_uploads/HkH7EF0ya.png)
觀察需要多一個Agent往Target的特徵，該特徵表示Agent到目標的方向向量。可以計算目標相對於Agent的相對位置，然後將該向量歸一化，以表示方向。
每次Agent觀察時，計算目標的相對方向向量，並將其添加到觀察中。這樣，Agent就能夠知道目標相對於自己的位置，包括目標是否在移動。
根據目標的方向向量，Agent可以調整其行為，例如朝向目標的方向移動，以追趕目標。

射線調整，距離牆壁的長度要調整



{%youtube 97ElaUAlflI %}
![](https://hackmd.io/_uploads/BklXtPhe6.png)


