最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Unity 實現(xiàn)框選游戲戰(zhàn)斗單位的思路詳解

 更新時間:2022年12月01日 09:45:36   作者:CoderZ1010  
這篇文章主要介紹了Unity 如何實現(xiàn)框選游戲戰(zhàn)斗單位,本文簡單介紹如何實現(xiàn)即時戰(zhàn)略游戲中框選戰(zhàn)斗單位的功能,需要的朋友可以參考下

?? Preface

本文簡單介紹如何實現(xiàn)即時戰(zhàn)略游戲中框選戰(zhàn)斗單位的功能,如圖所示:

?? 實現(xiàn)思路:

本文將該功能的實現(xiàn)拆分為以下部分:

  • 在屏幕坐標系中繪制框選范圍;
  • 根據(jù)框選范圍定位其在世界坐標系中對應(yīng)的區(qū)域;
  • 在該區(qū)域內(nèi)進行物理檢測。

? 如何在屏幕坐標系內(nèi)繪制框選框

使用Line Renderer光線渲染器組件來進行范圍繪制,當鼠標按下時,可以獲得框選范圍的起始點,鼠標持續(xù)按下時,鼠標位置則是框選范圍的結(jié)束點,根據(jù)這兩個點的坐標可以求得另外兩個頂點的坐標,如圖所示:

首先設(shè)置Line Renderer光線渲染器的屬性:

  • Enable:默認設(shè)為false,當鼠標按下時將其設(shè)為true;
  • Loop:設(shè)為true,為了讓第三個頂點與起始點相連形成閉環(huán);
  • Size:設(shè)為4,框選范圍有4個頂點;
  • Width:設(shè)為0.001即可,線框不需要很粗,可適當調(diào)整;

代碼部分:

using UnityEngine;
using SK.Framework;
using System.Collections.Generic;

public class Example : MonoBehaviour
{
    //光線渲染器組件
    private LineRenderer lineRenderer;
    //屏幕坐標系起始點
    private Vector3 screenStartPoint;
    //屏幕坐標系結(jié)束點
    private Vector3 screenEndPoint;
    
    private void Start()
    {
        //獲取光線渲染器組件
        lineRenderer = GetComponent<LineRenderer>();
    }

    private void Update()
    {
        //鼠標按下
        if (Input.GetMouseButtonDown(0))
        {
            //激活光線渲染器
            lineRenderer.enabled = true;
            //屏幕坐標系起始點
            screenStartPoint = Input.mousePosition;
            screenStartPoint.z = 1;
        }
        //鼠標持續(xù)按下
        if (Input.GetMouseButton(0))
        {
            //屏幕坐標系結(jié)束點
            screenEndPoint = Input.mousePosition;
            screenEndPoint.z = 1;
            //求得框選框的另外兩個頂點的位置
            Vector3 point1 = new Vector3(screenEndPoint.x, screenStartPoint.y, 1);
            Vector3 point2 = new Vector3(screenStartPoint.x, screenEndPoint.y, 1);
            
            //接下來使用光線渲染器畫出框選范圍
            lineRenderer.SetPosition(0, Camera.main.ScreenToWorldPoint(screenStartPoint));
            lineRenderer.SetPosition(1, Camera.main.ScreenToWorldPoint(point1));
            lineRenderer.SetPosition(2, Camera.main.ScreenToWorldPoint(screenEndPoint));
            lineRenderer.SetPosition(3, Camera.main.ScreenToWorldPoint(point2));
        }
        //鼠標抬起
        if (Input.GetMouseButtonUp(0))
        {
            //取消光線渲染器
            lineRenderer.enabled = false;
        }
    }
}

如圖所示,已經(jīng)實現(xiàn)框選范圍的繪制:

?? 根據(jù)框選范圍定位其在世界坐標系中對應(yīng)的區(qū)域

該部分的實現(xiàn)主要依靠物理射線檢測,在鼠標位置發(fā)出射線,檢測與地面的碰撞點,首先為Plane地面設(shè)置Layer層級:

在鼠標按下時根據(jù)射線檢測信息確定世界坐標系中的起始點:

//鼠標按下
if (Input.GetMouseButtonDown(0))
{
    //激活光線渲染器
    lineRenderer.enabled = true;
    //屏幕坐標系起始點
    screenStartPoint = Input.mousePosition;
    screenStartPoint.z = 1;
    //射線檢測
    if (Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 1 << LayerMask.NameToLayer("Ground")))
    {
        //世界坐標系起始點
        worldStartPoint = hit.point;
    }
}

在鼠標抬起時根據(jù)射線檢測信息確定世界坐標系中的結(jié)束點:

//鼠標抬起
if (Input.GetMouseButtonUp(0))
{
    //取消光線渲染器
    lineRenderer.enabled = false;

    //射線檢測
    if (Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 1 << LayerMask.NameToLayer("Ground")))
    {
        //世界坐標系結(jié)束點
        worldEndPoint = hit.point;
    }
}

?? 在該區(qū)域內(nèi)進行物理檢測

該部分用的的核心API:

可以理解為創(chuàng)建一個碰撞盒來檢測該范圍內(nèi)的碰撞體,首先計算出該API需要傳入的參數(shù):

  • center:該盒子的中心點;
  • halfExtents:該盒子長寬高的一半。
//盒子中心點
Vector3 center = new Vector3((worldEndPoint.x + worldStartPoint.x) * .5f, 1f, (worldEndPoint.z + worldStartPoint.z) * .5f);
//盒子長寬高的一半
Vector3 halfExtents = new Vector3(Mathf.Abs(worldEndPoint.x - worldStartPoint.x) * .5f, 1f, Mathf.Abs(worldEndPoint.z - worldStartPoint.z) * .5f);

有了這兩個參數(shù),調(diào)用該API可以獲得該區(qū)域內(nèi)的所有碰撞體,遍歷判斷碰撞體身上如果包含指定的組件,則將其選中,這里使用Outline高亮組件來表示:

//盒子中心點
Vector3 center = new Vector3((worldEndPoint.x + worldStartPoint.x) * .5f, 1f, (worldEndPoint.z + worldStartPoint.z) * .5f);
//盒子長寬高的一半
Vector3 halfExtents = new Vector3(Mathf.Abs(worldEndPoint.x - worldStartPoint.x) * .5f, 1f, Mathf.Abs(worldEndPoint.z - worldStartPoint.z) * .5f);
//檢測到盒子內(nèi)的碰撞器
Collider[] colliders = Physics.OverlapBox(center, halfExtents);

for (int i = 0; i < colliders.Length; i++)
{
    var collider = colliders[i];
    var outline = collider.GetComponent<Outline>();
    if (outline != null)
    {
        outline.enabled = true;
    }
}

如圖所示,我們已經(jīng)實現(xiàn)了基本的框選功能:

在框選時,還需要清除上一次框選的內(nèi)容,因此我們使用一個List列表來記錄當前框選的戰(zhàn)斗單位,框選前遍歷該列表來清除框選記錄,完整代碼如下:

public class Example : MonoBehaviour
{
    //光線渲染器組件
    private LineRenderer lineRenderer;
    //屏幕坐標系起始點
    private Vector3 screenStartPoint;
    //屏幕坐標系結(jié)束點
    private Vector3 screenEndPoint;
    //主相機
    private Camera mainCamera;
    //碰撞信息
    private RaycastHit hit;
    //世界坐標系起始點
    private Vector3 worldStartPoint;
    //世界坐標系結(jié)束點
    private Vector3 worldEndPoint;
    //框選記錄列表
    private List<Outline> list = new List<Outline>();

    private void Start()
    {
        //獲取光線渲染器組件
        lineRenderer = GetComponent<LineRenderer>();
        //獲取主相機
        mainCamera = Camera.main != null ? Camera.main : FindObjectOfType<Camera>();
    }

    private void Update()
    {
        //鼠標按下
        if (Input.GetMouseButtonDown(0))
        {
            //激活光線渲染器
            lineRenderer.enabled = true;
            //屏幕坐標系起始點
            screenStartPoint = Input.mousePosition;
            screenStartPoint.z = 1;
            //射線檢測
            if (Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 1 << LayerMask.NameToLayer("Ground")))
            {
                //世界坐標系起始點
                worldStartPoint = hit.point;
            }
        }
        //鼠標持續(xù)按下
        if (Input.GetMouseButton(0))
        {
            //屏幕坐標系結(jié)束點
            screenEndPoint = Input.mousePosition;
            screenEndPoint.z = 1;
            //求得框選框的另外兩個頂點的位置
            Vector3 point1 = new Vector3(screenEndPoint.x, screenStartPoint.y, 1);
            Vector3 point2 = new Vector3(screenStartPoint.x, screenEndPoint.y, 1);
            
            //接下來使用光線渲染器畫出框選范圍
            lineRenderer.SetPosition(0, Camera.main.ScreenToWorldPoint(screenStartPoint));
            lineRenderer.SetPosition(1, Camera.main.ScreenToWorldPoint(point1));
            lineRenderer.SetPosition(2, Camera.main.ScreenToWorldPoint(screenEndPoint));
            lineRenderer.SetPosition(3, Camera.main.ScreenToWorldPoint(point2));
        }
        //鼠標抬起
        if (Input.GetMouseButtonUp(0))
        {
            //取消光線渲染器
            lineRenderer.enabled = false;

            //首先清除上一次的框選記錄
            for (int i = 0; i < list.Count; i++)
            {
                list[i].enabled = false;
            }
            list.Clear();

            //射線檢測
            if (Physics.Raycast(mainCamera.ScreenPointToRay(Input.mousePosition), out hit, 1 << LayerMask.NameToLayer("Ground")))
            {
                //世界坐標系結(jié)束點
                worldEndPoint = hit.point;
                //盒子中心點
                Vector3 center = new Vector3((worldEndPoint.x + worldStartPoint.x) * .5f, 1f, (worldEndPoint.z + worldStartPoint.z) * .5f);
                //盒子長寬高的一半
                Vector3 halfExtents = new Vector3(Mathf.Abs(worldEndPoint.x - worldStartPoint.x) * .5f, 1f, Mathf.Abs(worldEndPoint.z - worldStartPoint.z) * .5f);
                //檢測到盒子內(nèi)的碰撞器
                Collider[] colliders = Physics.OverlapBox(center, halfExtents);

                for (int i = 0; i < colliders.Length; i++)
                {
                    var collider = colliders[i];
                    var outline = collider.GetComponent<Outline>();
                    if (outline != null)
                    {
                        list.Add(outline);
                        outline.enabled = true;
                    }
                }
            }
        }
    }
}

到此這篇關(guān)于Unity 如何實現(xiàn)框選游戲戰(zhàn)斗單位的文章就介紹到這了,更多相關(guān)Unity框選游戲戰(zhàn)斗單位內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • C#利用控件拖拽技術(shù)制作拼圖游戲

    C#利用控件拖拽技術(shù)制作拼圖游戲

    這篇文章主要介紹了C#利用控件拖拽技術(shù)制作拼圖游戲的方法以及核心代碼,需要的朋友可以參考下
    2015-06-06
  • C#中 paint()與Onpaint()的區(qū)別

    C#中 paint()與Onpaint()的區(qū)別

    paint是事件onpaint方法onpaint方法是調(diào)用paint事件的,用哪一個,效果是一樣,就看那一個方便了內(nèi)部是這樣實現(xiàn)的:
    2013-04-04
  • c#實現(xiàn)字符串反序輸出字符串的實例

    c#實現(xiàn)字符串反序輸出字符串的實例

    下面小編就為大家分享一篇c#實現(xiàn)字符串反序輸出字符串的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2017-12-12
  • 如何用.NETCore操作RabbitMQ

    如何用.NETCore操作RabbitMQ

    這篇文章主要介紹了如何用.NETCore操作RabbitMQ,對中間件感興趣的同學(xué),可以參考下
    2021-05-05
  • C#中Response.Write常見問題匯總

    C#中Response.Write常見問題匯總

    這篇文章主要介紹了C#中Response.Write常見問題匯總,總結(jié)了C#中Response.Write的常用技巧,非常實用,需要的朋友可以參考下
    2014-09-09
  • 如何利用c#實現(xiàn)通用守護進程

    如何利用c#實現(xiàn)通用守護進程

    這篇文章主要給大家介紹了關(guān)于如何利用c#實現(xiàn)通用守護進程的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習或者使用c#具有一定的參考學(xué)習價值,需要的朋友們下面來一起學(xué)習學(xué)習吧
    2019-10-10
  • 簡單實現(xiàn)C#異步操作

    簡單實現(xiàn)C#異步操作

    這篇文章主要為大家詳細介紹了C#簡單實現(xiàn)異步操作的方法,通過BeginInvoke、EndInvoke的方式實現(xiàn)異步編程,感興趣的小伙伴們可以參考一下
    2016-02-02
  • WPF PasswordBox進行數(shù)據(jù)綁定方法

    WPF PasswordBox進行數(shù)據(jù)綁定方法

    有的時候會遇見PasswordBox的Password屬性不是依賴屬性,因此無法進行數(shù)據(jù)綁定。本文介紹如何通過添加附加屬性解決該問題,有此問題的同學(xué)可以參考下本文
    2021-06-06
  • 在Winform動態(tài)啟動、控制臺命令行的方法

    在Winform動態(tài)啟動、控制臺命令行的方法

    winForm 程序輸出類型為 windows 程序(不是命令行程序)在運行時想輸入一些信息編譯開發(fā)調(diào)試,如何實現(xiàn)這一功能
    2013-02-02
  • C#中FileSystemWatcher類實現(xiàn)監(jiān)控文件夾

    C#中FileSystemWatcher類實現(xiàn)監(jiān)控文件夾

    在C#中,如果你想要監(jiān)控一個文件夾內(nèi)文件的變動情況,比如文件的創(chuàng)建、刪除、修改等,你可以使用FileSystemWatcher類,下面就來介紹一下FileSystemWatcher監(jiān)控的使用,感興趣的可以了解一下
    2024-03-03

最新評論

定西市| 纳雍县| 张家川| 专栏| 二连浩特市| 乐亭县| 温泉县| 广州市| 确山县| 双鸭山市| 澎湖县| 安阳市| 柞水县| 龙川县| 惠水县| 乡城县| 哈巴河县| 布拖县| 建德市| 铜陵市| 三亚市| 石柱| 晋城| 兰考县| 大冶市| 长沙市| 保康县| 平陆县| 永济市| 祥云县| 丰都县| 乐都县| 新余市| 静海县| 屏东县| 南溪县| 双桥区| 兖州市| 鹤山市| 鹰潭市| 兴宁市|