創作內容

5 GP

Unity的 RTS戰爭迷霧 視野障礙

作者:樂小呈│2019-09-11 11:30:43│巴幣:10│人氣:359
阿阿啊啊啊黑歷史系列別看啦,誤人子弟。゚ヽ(゚´Д`)ノ゚。

上一篇

我還不太會寫這種文,所以如果有那裡看不懂、不清楚的,請一定要提出!

把視野障礙的功能做出來了
一樣是用物理碰撞,簡單暴力
效果↓


來講作法

主要的概念就是
先用圓形碰撞判斷視野範圍內有沒有[障礙物]
再用Raycast判斷有哪些部分是受到阻擋的

記得新增一個Layer給障礙物用,我是用Block

首先是變數~
Sight - 新增兩個變數
LayerMask blockLayer - 用來分辨障礙物的Layer,記得要到Inspector指定給障礙物Layer
bool showDebug - 用來Debug的,可加可不加
    [SerializeField] float sightRange = 1;
    public float SightRange { get => sightRange; }

    [SerializeField] LayerMask blockLayer;                                                                 //New

    [SerializeField] bool showDebug = false;                                                               //New

FogManager - 變數改名
List<SpriteRenderer> fogs 改成  mapFogs
List<Sight> sights 改成 allSights
  [SerializeField] Vector3 mapScale;
    [SerializeField] Vector3 fogScale = Vector3.up;
    [SerializeField] SpriteRenderer fogSprite;                                                              


    List<SpriteRenderer> mapFogs = new List<SpriteRenderer>();                             //改名
    [SerializeField] List<Sight> allSights = new List<Sight>();                                      //改名

變數就這樣了
然後是程式的部分
FogManager  -  更新霧塊狀態
先找出視線範圍中受到阻擋的部分,然後把視線範圍中受到阻擋的部分移除,
剩下的就是視線範圍中不受阻擋的部分,最後再更改霧塊狀態
    void UpdateFogs()
    
{
        ResetFogs();

        foreach (var sight in allSights)
        {
            List<SpriteRenderer> fogInSight = mapFogs.FindAll
                   (n => Vector3.Distance
(n.transform.position, sight.transform.position)
                   < sight.SightRange);


            List<SpriteRenderer> sightBlock = sight.SightBlock(fogInSight);                    
                                                                                                       //找出視線範圍中受到阻擋的部分

            List<SpriteRenderer> sights = fogInSight.Except(sightBlock).ToList();
                                                                                                      //
找出視線範圍中不受阻擋的部分
            
            FogLight(fogInSight, sights);                                              //更改霧塊狀態
         
        }
    }

Sight - 判斷視野中的障礙物及被遮擋的區域
先判斷視野範圍中有沒有[障礙物],再決定要不要執行障礙判斷
發射一條射線,從視野中心到目標物霧塊,如果這條線打中障礙物,就代表看向這塊霧的視線是受到阻擋的
再把受到阻擋的霧塊存入List,並檢查下一個霧塊
最後把所有視野中受到阻擋的霧塊回傳
    public List<SpriteRenderer> SightBlock(List<SpriteRenderer> fogs)
    
{
        bool blockCheck = Physics2D.OverlapCircle(transform.position, sightRange, blockLayer);
                      //
判斷視野範圍中有沒有[障礙物],用blockLayer來分辨

        if (!blockCheck) { return new List<SpriteRenderer>() ; }
                     //如果視野中沒有任何
[障礙物],回傳空 List

        List<SpriteRenderer> blockSight = new List<SpriteRenderer>();

        foreach (var fogSprite in fogs)                                                 
        {          
  //檢查視線中每一個霧塊
            Vector3 dirction = transform.position - fogSprite.transform.position ;
                     //計算霧塊對於自己的方向
,Raycast需要用到


            float distance = Vector3.Distance(transform.position, fogSprite.transform.position);
                    //計算目標霧塊與自身的距離,Raycast需要用到

            bool isBlocking = Physics2D.Raycast(fogSprite.transform.position, dirction, distance, blockLayer);
                    //發射一條射線,檢查霧塊和自己之間有沒有受到[障礙物]阻擋

            if (!isBlocking) { continue; }
                    //判斷
有沒有受到[障礙物]阻擋


            if (showDebug)
            {
                Debug.DrawRay(fogSprite.transform.position, dirction, Color.red);
                  //Debug用的,顯示判斷的線
            }

             blockSight.Add(fogSprite);
         
                 //把受到阻擋的霧塊加入List
            
        }

        return blockSight;      
                //回傳所有
受到阻擋的霧塊
    }
Debug線的樣子如下,只有線

有了視野障礙的資料,最後就是實際更改霧塊La
FogManager - 更改霧塊狀態
這裡我把視線分成兩部分
完整視野範圍中的霧塊設置不透明,這很不合理,等等會解釋原因
視野中未受阻擋的霧塊隱藏,做出視線效果
  void FogLight(List<SpriteRenderer> lightFogs, List<SpriteRenderer> sights)
    
{
        foreach (var lightFog in lightFogs)                                 //把視野範圍中的霧塊設置不透明
        {     
            Color fogColor = lightFog.color;
            fogColor.a = 0.5f;

            lightFog.color = fogColor;
        }

        foreach (var sight in sights)                                           
//把視線中的霧塊隱藏
        {
            sight.gameObject.SetActive(false);
        }
    }
OK 來說為什麼視野中受到阻擋的霧塊還要被[開圖]
因為只開視線看到的圖會變這樣↓
中間黑黑的很醜,如果有Shader讓霧好看一點其實就不用

\\\完成///
任何物件只要具有BoxCollider2D以及Layer設定成block,就可以具有阻擋視線的效果了~

如我有任何不清楚的地方請跟我說
這種教學?我還不清楚怎麼寫會比較好理解XD

然後!!
說到RTS怎麼能沒有建築物呢~
在視線中會有動畫,在離開視線時會是靜態的
畢竟建築物不會自己跑掉?
等下一篇吧(ゝ∀・)   幹寫這篇比做這些還累


效能的部分XD
把霧塊大小改成0.1單位
一共有 11*11  / 0.1 * 0.1  塊霧
(地圖尺寸)      (霧塊大小)
FPS剩下30
估計是這行搞的鬼,霧塊太多了XD
List<SpriteRenderer> fogInSight = mapFogs.FindAll(n => Vector3.Distance
(n.transform.position, sight.transform.position) < sight.SightRange);
之後應該會換個作法


題外話
我的YT推薦欄真U質


Brilliant



引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4525398
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:Unity

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

5喜歡★angus945 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:Unity的 RTS戰爭... 後一篇:【建模】 LowPoly...

追蹤私訊切換新版閱覽

作品資料夾

zzz54872qw想要重來的你
【敬啟:無法重來的你。】第四章-第六節-被捕獲的影子。即將步入結局!歡迎來我的小說看看喔!看更多我要大聲說8小時前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】