Traffic System use waypoint in Unity-Section2

前言

在前一篇的時候我們利用了waypoint以及CharacterNavigationController 可以讓我們的角色可以在我們指定的Waypoint走動,如果想繼續學習的人可以先看一下上一篇

Traffic System use waypoint in Unity-Section1

接著的這一篇主要學習如何讓我們的人物可以生成更多以及不同路線的相接,讓我們的NPC可以不僅僅在一個圈圈裏面繞更可以靠著AI隨機讓這群人可以在城市裏面隨意亂走。

因為這兩篇的C#語法數量蠻大的,如果有興趣練習的朋友可以到這裡下載檔案

Waypoint Script All

PedestrianSpawner

為了讓行人可以變多,我們需要在Scrpit裡面新增一個C#語法,並重新命名為 PedestrianSpawner ,利用父子關係的語法重複產生相同的角色。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PedestrianSpawner : MonoBehaviour
{
    public GameObject pedestrianPrefab;
    public int pedestriansTopSpawn;
    
    void Start()
    {
        StartCoroutine(Spawn());//呼叫Spawn重複產生在Waypoint上

    }

    IEnumerator Spawn()
    {
        int count = 0;
        while(count<pedestriansTopSpawn)
        {
            GameObject obj = Instantiate(pedestrianPrefab);
            Transform child = transform.GetChild(Random.Range(0, transform.childCount - 1));
            obj.GetComponent<WaypointNavigator>().currentWaypoint = child.GetComponent<Waypoint>();
            obj.transform.position = child.position;

            yield return new WaitForEndOfFrame();

            count++;


        }
    }
}

建立好 PedestrianSpawner 以後我們將語法掛在Waypoint上面,並將我們的角色Perfab拉進 PedestrianSpawner 的 PedestrianPrefab裡面當作source,並在 PedestrianS Top Spwan裡面輸入你要的數量。

接著我們按下Play就可以看到角色猶如蟑螂一般的生成出來了。

這時候我們可以看到所有的人都是同個速度在行走,這個在真實世界裡面是很奇怪的,而且同樣的人所有的速度速率都是一樣的,連行走的方向都是一致讓人感到相當的不舒服。

WaypointNavigtor

這邊我們需要打開我們的WaypointNavigtor進行修改,首先我們新增一個Driretion

int direction;

接著在原本的Controller上面設定生成的速度

 direction = Mathf.RoundToInt(UnityEngine.Random.Range(0f, 1f));//生成的速度

然後最後我們給他一個可以在下一個Waypoint隨機生成的語法,依照不同的方向行走

void Update()
    {

        //在不同的nextWaypoint生成
        if(controller.reachedDestination)
        {
            if(direction == 0)
            {
                currentWaypoint = currentWaypoint.nextWaypoint;
            }
            else if(direction == 1)
            {
                currentWaypoint = currentWaypoint.previousWaypoint;
           

        }
            controller.SetDestination(currentWaypoint.GetPosition());
        }
    }

按下play以後我們可以看到所有的人已經步是朝一個方向而且走路的速度已經不會這麼統一,雖然沒有很完美但是看起來已經比剛剛好很多了。

Waypoint

接著我們讓這些人走出舒適圈,讓它們不要只在這個區域繞圈圈,首先打開Waypoint的檔案修改

這邊新增一個branches

public List<Waypoint> branches;

WaypointEditos

同時我們這邊也需要打開我們的WaypointEditos,讓branches這邊一樣給他有Gizmos顏色的可以讓我們輕易分辨的視覺

//顯示branches顏色
        if (waypoint.branches !=null )
        {
            foreach(Waypoint branch in waypoint.branches)
            {
                Gizmos.color = Color.blue;
                Gizmos.DrawLine(waypoint.transform.position, branch.transform.position);
            }
        }

WaypointManagerWindow

接著我們打開WaypointManagerWindow新增一個Branch

 if(GUILayout.Button("Add Branch Waypoint"))
            {
                CreateBranch();
            }

在下面我們指定branch到之前我們舊的Waypoint

//指定到舊的waypoint
    void CreateBranch()
    {
        GameObject waypointObject = new GameObject("Waypoint" + waypointRoot.childCount, typeof(Waypoint));
        waypointObject.transform.SetParent(waypointRoot, false);

        Waypoint waypoint = waypointObject.GetComponent<Waypoint>();

        Waypoint branchedFrom = Selection.activeGameObject.GetComponent<Waypoint>();
        branchedFrom.branches.Add(waypoint);

        waypoint.transform.position = branchedFrom.transform.position;
        waypoint.transform.forward = branchedFrom.transform.forward;

        Selection.activeGameObject = waypoint.gameObject;

    }

Waypoint

然後我們回到我們的Waypoint語法檔案,這邊指定呼叫branch的Ratio range 0到1之間並從0.5f開始

    public List<Waypoint> branches = new List<Waypoint>();

    [Range(0f, 1f)]
    public float branchRatio = 0.5f;//呼叫branch range 0到1之間並從0.5f開始 

WaypointNavigator

然後我們接著修改WaypointNavigator的部分,這邊我們需要檢查當前是否有branch所以在原本的if (controller.reachedDestination)內寫下

  //檢查當前是否有branch
            bool shouldBranch = false;

            if (currentWaypoint.branches != null && currentWaypoint.branches.Count > 0)
            {
                shouldBranch = Random.Range(0f, 1f) <= currentWaypoint.branchRatio ? true : false;
            }

            //如果確定有branch隨機挑選下一個waypoint位置
            if (shouldBranch)
            {
                currentWaypoint = currentWaypoint.branches[Random.Range(0, currentWaypoint.branches.Count - 1)];

            }

如果沒有的話就更改direction,這邊以direction的0或1作判別。

 //如果沒有就更改direction
            else
            {
                if (direction == 0)
                {
                    if (currentWaypoint.nextWaypoint != null)
                    {
                        currentWaypoint = currentWaypoint.nextWaypoint;
                    }
                    else
                    {
                        currentWaypoint = currentWaypoint.previousWaypoint;
                        direction = 1;
                    }
                }
                else if (direction == 1)
                {
                    if (currentWaypoint.previousWaypoint != null)
                    {
                        currentWaypoint = currentWaypoint.previousWaypoint;
                    }
                    else
                    {
                        currentWaypoint = currentWaypoint.nextWaypoint;
                    }
                }

Branch

一切就緒以後我們可以在WaypointManagerWindow裡面看到多了一個Add Branch Waypoint的按鈕,這邊可以依照自己哪一段的waypointBranch出來,並繼續Create Waypoint。

測試看看Waypoint可以發現我們可以讓我們的NPC多了不同的道路可以走動。

按下Play以後可以看到我們的人物卡在馬路中間轉圈圈,因為目前的NODE會讓它們只能進不能出

這邊我們在原本的Branch Node新增一個Waypoint並將Branch Ratio設為1,接著將新增的waypoint連到要出去的那一個Waypoint這樣就會變成有出入口的段落了。


將要讓人物走出去的 waypoint Branch Ratio 設為1

這樣就可以看到大家可以過馬路了,不會在馬路上繞圈圈了。

小結

要製作Traffic System需要蠻多的語法控制以及Waypoint的設定,雖然過程蠻辛苦的但是看到成果也是覺得相當值得的,如果要更好的效果可能還需要在鑽研一下,但也是一個好的開始。

資料來源:https://www.youtube.com/watch?v=MXCZ-n5VyJc&t=601s

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *