国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Unity2D實現(xiàn)子彈追蹤目標

這篇具有很好參考價值的文章主要介紹了Unity2D實現(xiàn)子彈追蹤目標。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

實現(xiàn)子彈追蹤目標有很多種方法,首先是一開始就選定了目標的位置,然后按照曲線運動軌跡的方式,持續(xù)運動到目標點,不過如果目標移動了,就得將對應的軌跡重新計算一次,另外如果需要設(shè)置范圍的話更不好做。另一種是銳角追蹤,就是在目標進入識別范圍后,將子彈的旋轉(zhuǎn)方向朝向目標,但是這會使得子彈的拐彎看起來非常的突兀,舉個列子就是如果敵人時在子彈后進入了識別范圍,那么就會導致子彈突然來個180度大轉(zhuǎn)彎,很不美觀,還有一種就是給子彈施加一個朝向目標力,問題是會帶來子彈的速度大小改變,繼而還要標準化速度,而且追蹤的定位可能不準,因為子彈有初速度。

我所用的追蹤是在銳角轉(zhuǎn)彎上的思路改進,就是將修改子彈的旋轉(zhuǎn)朝向向目標位置但是每次只更改一點角度,直到子彈方向指向目標后將不再旋轉(zhuǎn)。

把大概的效果圖放一下先~

Unity2D實現(xiàn)子彈追蹤目標

考慮到追蹤的范圍識別問題,有兩個解決方法,一種是用collider,但是當子彈非常多的時候性能開銷可能會很大,導致掉幀。另一種是代碼替代,這個之后詳細再講,不過我的相比碰撞也不會節(jié)省多少......

先來講講使用碰撞箱的這種較為容易理解的邏輯

我用上的屬性:

? ? [Range(0, 100)]
    [SerializeField]
    private int hurt;//傷害

    [Range(0, 100)]
    [SerializeField]
    private float speed;//速度

    private GameObject enemy;//敵人對象

    [Range(0, 10)]
    [SerializeField]
    private float angle_differ;//允許的差異角度

    [Range(0, 2)]
    [SerializeField]
    private float angle_fix;//每次修正的角度

    [Range(0, 100)]
    [SerializeField]
    private float dis_time;//消失時間

想要獲取到要追蹤的物體,就需要一個添加一個圓形碰撞箱,然后勾選其是觸發(fā)器選項,這里的盒體碰撞是為了檢測子彈和敵人發(fā)生碰撞時執(zhí)行傷害事件才使用的,這里不做說明。

當這物體進入碰撞箱后,就將這個物體賦值給enemy,具體代碼如下:

    //因為存在不足,我沒用使用這個方法
    private void OnTriggerEnter2D(Collider2D collision)
    {
? ? ? ? //嘗試過進行獲取多個敵人對象然后選擇對象
? ? ? ? //AI_Move[] enemys = collision.GetComponentsInChildren<AI_Move>();
? ? ? ? 
? ? ? ? //判斷是否有敵人組件,否則enemy為null,無法賦值給this.enemy
        AI_Move enemy = collision.gameObject.GetComponent<AI_Move>();
        if (enemy != null)
        {
? ? ? ? ? ? //指定敵人目標
            this.enemy = collision.gameObject;
        }
    }

只要當敵人進入圓形碰撞箱后,就會執(zhí)行這個函數(shù),然后將這個敵人對象賦給enemy,這樣就相當于告訴知道子彈應該追蹤那個物體了。

接下來就是重點,子彈已經(jīng)知道應該去追蹤誰了,那么如何將使得子彈轉(zhuǎn)向敵人的位置呢?首先必須使得子彈在旋轉(zhuǎn)不會影響自身的速度大小。我這里使用的是

transform.Translate(speed * Time.deltaTime, 0, 0);

這個方法來控制子彈的移動。這段代碼是使得子彈沿著自身x軸方向運動,當它的世界旋轉(zhuǎn)方向改變時,x軸的軸向也會變動,這樣使得無論如何改變它的角度也不會改變他的速度大小。

然后執(zhí)行如下代碼

? ? ? ? //檢測到敵人時則執(zhí)行追蹤
        if (enemy != null)
        {
            //對需要追蹤物體和自身間的角度求解運算
            Vector2 row = (enemy.transform.position - transform.position).normalized;
            //獲取兩物體間夾角
            float angle1 = Vector3.SignedAngle(Vector3.up, row, Vector3.forward);
            //將夾角坐標和世界坐標的取值和范圍對齊
            angle1 = (angle1 + 270) % 360;
            //獲取彈幕自身世界坐標
            float angle2 = transform.eulerAngles.z % 360;
            //獲取兩個角度間的差異值并標準化
            float angle3 = ((angle1 - angle2) + 360) % 360;


            //對物體的角度做修正,使得物體x軸指向需要追蹤的目標
            //朝向需要追蹤對象的方向調(diào)整角度,按照設(shè)定的值進行調(diào)整
            if (angle3 < 180 - angle_differ)
            {
                Quaternion reAngle = Quaternion.Euler(0, 0, transform.eulerAngles.z - angle_fix);
                transform.rotation = reAngle;
            }
            else if (angle3 > 180 + angle_differ)
            {
                Quaternion reAngle = Quaternion.Euler(0, 0, transform.eulerAngles.z + angle_fix);
                transform.rotation = reAngle;
            }

        }

計算角度使用unity自帶的SignedAngle方法就可以算出兩個物體間的夾角,接下來但是問題在于,夾角使用的取值范圍和世界坐標的旋轉(zhuǎn)的標準不一樣,夾角計算出的結(jié)果返回的是一個-180到180的區(qū)間,而世界坐標則是是0~360的一個區(qū)間而且兩者的起點0位置不同。如果你不清楚這個差異會導致的問題,你可以看看接下來的圖解和不這樣寫子彈的運行軌跡。

Unity2D實現(xiàn)子彈追蹤目標

上面的A1 A2分別代表angle1和angle2,可以看出,在第二第三第四象限,同樣位置的角度在A1坐標下減去A2,得到的都是-270,但是唯獨在第一坐標下的值為90。同樣的我們看看不對angle1和angle3進行模運算修正的結(jié)果,此時指向角的差值不為180而是-90。我們來看看此時子彈指向物體會出現(xiàn)什么問題。

Unity2D實現(xiàn)子彈追蹤目標

可以看到,在位于敵人左上方時,指向就發(fā)生了混亂,就是我所說的坐標系標準問題。

有人就會覺得只要簡單的對angle3做360的模運算就可以了,實際上我就這么認為過,然后......

Unity2D實現(xiàn)子彈追蹤目標

很明顯實際上沒有這樣簡單,子彈仍然在某些位置上會發(fā)生奇怪的偏轉(zhuǎn),需要考慮到16種情況,每一個坐標系上都會有四種。(朝向物體但角度偏大,偏小,背向物體的兩個偏向,因為你總不可能只采用一個方向的角度修正吧,不然明明能往左轉(zhuǎn)就能到非要向右繞一圈回來)

總之,大概就是這樣,如果你仍然不能理解后果,可以自己試一試按照我的方式寫一下會不會出現(xiàn)這種問題,反正當時解決這個問題把我整慘了。

將兩者的坐標的值都對齊后,如何使得子彈的旋轉(zhuǎn)指向物體呢?就像是我們要面對面看著你,相互錯位180度就可以了。如果想要控制子彈的追蹤距離限制,可以設(shè)置圓形碰撞器的大小,修改angle_fix使得每次旋轉(zhuǎn)的角度變化更大或更小,這樣轉(zhuǎn)彎也會越明顯或不明顯,angle_differ其實沒有太大的意義,只是設(shè)置讓它指向差錯角度大小的調(diào)整,可以不使用讓它只鎖定中心。

接下來是第二種方法

之所以我棄用了使用碰撞器的方法,一是性能開銷問題,當發(fā)射大量子彈后,使用圓形碰撞判斷范圍內(nèi)是否有敵人會消耗很大性能,二是我使用的unity版本的圓形碰撞器有些bug,導致失去enemy對象(明明物體還在范圍內(nèi)結(jié)果判定出了碰撞,要不是debug了不然我還不信)三是如果按照我寫的方式,每次單個檢測,一但當有第二個敵人進入碰撞,那么就會覆蓋子彈的enemy就會被覆蓋并指向下一個敵人,條件苛刻點甚至能出現(xiàn)子彈從一堆敵人中繞過去,當然要改代碼也是能解決這個問題的,但是相比這個方法屬實不劃算。

另一種方式來設(shè)置enemy

    private void OnArea()
    {
        //相對上面的方式能夠減少性能開銷,而且能指定選擇的對象
        GameObject[] games = GameObject.FindGameObjectsWithTag("Enemy");
        //設(shè)置當前最近需要追蹤對象的距離,如果結(jié)束后這個值沒有變說明范圍內(nèi)沒有敵人
        float distance = this.distance;
        foreach(GameObject game in games)
        {
            //這句其實是多余的,因為目前測試場景中可被追蹤的敵人都是這個標簽,但是也可以保留
            //可以在此基礎(chǔ)上發(fā)展追蹤優(yōu)先級,的比如同距離優(yōu)先鎖定BOSS,或者不能被追蹤的敵人對象
            if (game.GetComponent<AI_Move>() != null)
            {
                //找到場景中指定為敵人的對象,進行距離求值運算
                float dis = Vector2.Distance(new(game.transform.position.x, game.transform.position.y),
                    new(gameObject.transform.position.x, gameObject.transform.position.y));
                if (distance > dis)
                {
                    //將最小距離的GameObject對象賦值給需要追蹤的對象enemy,會不斷的循環(huán)更替,最終結(jié)束循環(huán)的時候
                    //篩選出來的enemy就是距離這個彈幕最近的敵人
                    distance = dis;
                    enemy = game;
                }
            }
        }
        if (distance == this.distance)
        {
            //如果沒有找到或者飛行過程中脫離了最大追蹤距離,刪除追蹤對象
            enemy = null;
        }
    }
}

接下來只需要在Update()方法執(zhí)行這個方法就可以了。

這種方式能解決以上的所有問題,而且可以通過設(shè)置time固定時間調(diào)用一次使得不必每幀執(zhí)行這個方法,繼續(xù)減少開銷(......),由于獲取了一個數(shù)組的敵人,可以通過Tag值區(qū)分敵人類型,那些不能被追蹤那些能,還可以在給distance除一個數(shù)分層追蹤的優(yōu)先級,比如同距離優(yōu)先鎖定BOSS等等擴展方法,相對于使用碰撞使用這個實現(xiàn)更容易。

不過子彈追蹤的方式還有很多種,肯定有更好的方法來實現(xiàn)子彈追蹤,不過大概我寫的比較容易理解適合萌新吧,畢竟我也在這個層級......

把追蹤腳本掛載在了一個分裂體子彈上,效果看起來不錯,也很流暢。文章來源地址http://www.zghlxwxcb.cn/news/detail-459457.html

Unity2D實現(xiàn)子彈追蹤目標

到了這里,關(guān)于Unity2D實現(xiàn)子彈追蹤目標的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • unity2d實現(xiàn)一個全方位的無限隨機地圖

    要實現(xiàn)一個全方位的無限隨機地圖,可以考慮以下步驟: 1.創(chuàng)建一個空的場景,并添加一個相機和一個玩家對象。 2.創(chuàng)建一個TileMap,它將作為你的地圖板塊。你可以使用隨機數(shù)生成算法生成各種類型的地形,如森林、草地、沙漠等等,并使用TileMap將它們組裝在一起來創(chuàng)建你

    2024年02月07日
    瀏覽(24)
  • 【Unity2D】實現(xiàn)打怪掉落物品(如爆金幣等)的功能

    【Unity2D】實現(xiàn)打怪掉落物品(如爆金幣等)的功能

    本文章記錄實現(xiàn)打怪掉落物品的功能,以下代碼為2D實現(xiàn),3D模式稍加修改即可。 目錄 一、代碼部分 二、注意事項 三、效果展示 創(chuàng)建一個C#腳本命名為Item,并將該腳本掛載到需要掉落的物品上。 1.需要禁用掉落物品與自身和其他人物之間的碰撞(否則可能被物品撞飛)。

    2024年02月11日
    瀏覽(28)
  • Unity2D 實現(xiàn)UGUI滾動鼠標滑輪以鼠標位置點為中心縮放圖片

    Unity2D 實現(xiàn)UGUI滾動鼠標滑輪以鼠標位置點為中心縮放圖片

    ?先放參考文章: Unity3d UGUI以鼠標位置點為中心縮放圖片(含項目源碼) https://blog.csdn.net/qq_33789001/article/details/117749837 再放實現(xiàn)效果: 說說事情緣由,項目需要用到這個效果,所以上網(wǎng)找了個參考文章,后來不知道為什么失效了,所以想著自己改改,看看是什么毛病。 貼原

    2024年02月11日
    瀏覽(20)
  • Unity常用2D子彈彈幕以及槍械類型的實現(xiàn):可實現(xiàn)霰彈槍,Boss彈幕,子彈反彈,追蹤彈等

    Unity常用2D子彈彈幕以及槍械類型的實現(xiàn):可實現(xiàn)霰彈槍,Boss彈幕,子彈反彈,追蹤彈等

    Hello大家好我是開羅小8,今天我來給大家?guī)鞺nity常用子彈彈幕類型的實現(xiàn),功能的實現(xiàn)方式有很多種,在實現(xiàn)效果中,我會盡可能用簡單的代碼實現(xiàn), 文章的示例項目文件在文章底部 環(huán)形彈幕實現(xiàn) 追蹤彈 本文 子彈始終朝向其前進方向移動 (在2D中紅軸為前進方向,3D中藍

    2024年02月05日
    瀏覽(39)
  • Unity2D學習筆記-Tilemap

    Unity2D學習筆記-Tilemap

    tilemap算是接觸了幾次,但是無論是看視頻還是看文章都一知半解,這次把編輯地圖的開始步驟搞清楚。 首先要知道tilemap是做什么的。 這里提到的Tilemap其實不止是Tilemap:Tilemap本身是地圖編輯器(雖然我更傾向于理解為“場景”,不過編輯地圖才是核心)。之前學的印象是,

    2023年04月09日
    瀏覽(26)
  • Unity2D控制角色左右移動

    Unity2D控制角色左右移動

    1.在Hierarchy一欄中選中角色; 2.在inspector欄最底端找到Add Component選項并點擊; 3.添加Rigidbody2D,合適的collider和new script; 4.將添加的Rigidbody2D拖到new script中; ? 5.在project欄中找到新添加的C#文件并雙擊打開(如果還沒有編輯代碼的工具,推薦Vscode) 6.代碼如下: using System.Nu

    2024年02月14日
    瀏覽(30)
  • Unity2D繪制游戲地圖

    Unity2D繪制游戲地圖

    首先,我們選擇我們的地圖素材(由于筆者在前段時間已經(jīng)進行切割,最近才開始整理這一段,所以這個是用的老素材,可能有朋友就會覺得切割前后不一致,但是思路是一樣的,大家學習思路即可) ?接著,我們找到右上角的Slice進行圖片切割,我這邊簡單介紹一下這個切

    2024年02月08日
    瀏覽(30)
  • Unity2D小狐貍教程筆記

    Unity2D小狐貍教程筆記

    下載 https://unity.cn/releases 默認顯示方式 window - layout - default SampleScene : Project - 文件目錄 Scene -游戲畫面 asset store - 素材商店 在asset store下載素材 sunnyland shift + sapace 放大窗口 1.背景導入 每個格子16像素: Pixels Per Unit 16px 2.繪制瓷磚式地圖 新建瓦片圖層:左上角/右鍵 2D object

    2024年01月24日
    瀏覽(32)
  • Unity2d游戲項目--小狐貍

    Unity2d游戲項目--小狐貍

    (一) 在文件夾中找到back圖片,并在檢查器面板中將back圖片的每單位像素數(shù)設(shè)置為16。 (文件所在地) (面板設(shè)置) (二) 將圖片拖入到場景中 (一) 生成矩形的瓦片地圖 (二) 打開平鋪調(diào)色板 (三) 新建并命名為map,在原目錄新建一個文件夾,用于存放你在這個瓦

    2024年02月03日
    瀏覽(32)
  • 【Unity2D】角色動畫的切換

    【Unity2D】角色動畫的切換

    第一種方法是設(shè)置一個中間狀態(tài),從中間狀態(tài)向其余各種狀態(tài)切換,且各狀態(tài)向其他狀態(tài)需要設(shè)置參數(shù) 實現(xiàn)動作轉(zhuǎn)移時右鍵點擊Make Transition即可? 實現(xiàn)動畫轉(zhuǎn)移需要設(shè)置條件 點擊一種動畫到另一種動畫的線 ,然后點擊加號添加Condition 比如機器人從向左走切換到向右走的條件

    2024年02月15日
    瀏覽(21)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包