主頁 >  其他 > 【游戲開發創新】使用Unity制作方陣編隊,CSDN方陣迎面走來,感謝CSDN的中秋禮物(影像采樣 | 點陣 | 方陣 | 隊形 | 變換 | 影片)

【游戲開發創新】使用Unity制作方陣編隊,CSDN方陣迎面走來,感謝CSDN的中秋禮物(影像采樣 | 點陣 | 方陣 | 隊形 | 變換 | 影片)

2021-09-02 07:10:10 其他

文章目錄

      • 一、前言
      • 二、運行效果
      • 三、實作原理
      • 四、圖片資源
      • 五、模型資源
      • 六、像素采樣,生成點陣
      • 七、根據點陣生成角色方陣
      • 八、方陣行走
      • 九、方陣變換
      • 十、工程原始碼
      • 十一、完畢

一、前言

嗨,大家好,我是新發,
最近一直在忙一些事情,好幾天沒寫文章了,前天收到CSDN的中秋禮物通知,非常感謝,特地做個小Demo感謝一下CSDN

二、運行效果

運行效果如下,方陣迎面跑來,
請添加圖片描述
CSDN方陣,
請添加圖片描述
陣型變換,
請添加圖片描述

請添加圖片描述

三、實作原理

實作原理很簡單,畫成圖是這樣子,

在這里插入圖片描述
下面我來講下具體的實作細節~

四、圖片資源

準備兩張圖片,如下:
在這里插入圖片描述
在這里插入圖片描述
勾選Read/Write Enabled,設定圖片為可讀,如下:
在這里插入圖片描述

五、模型資源

準備一個模型資源,
請添加圖片描述

帶一個站立和跑步影片,
請添加圖片描述

請添加圖片描述
影片狀態機如下,使用混合樹(Blend Tree)來過渡站立和跑影片,
在這里插入圖片描述
混合樹內部如下,通過Speed變數來控制混合:
請添加圖片描述
Speed變數(Float型別)如下:
在這里插入圖片描述
混合設定如下:
在這里插入圖片描述

六、像素采樣,生成點陣

像素采樣生成點陣的邏輯,我封裝在TextureFormation腳本中,

圖片像素采樣,我們可以使用Texture2DGetPixel介面,

public Color GetPixel(int x, int y);

我們可以把一張圖切割成很多個小正方塊(小方塊的邊長為samplingStep),比如像這樣子,
在這里插入圖片描述
對每個小方塊進行逐像素采樣,我們知道,一個像素的顏色是由RGBA四個通道值來表示的,每個通道的取值范圍是0~255
在這里插入圖片描述
對應到Color這個類,就是rgba
在這里插入圖片描述
這里要注意,Colorrgba是歸一化的,也就是取值范圍是0~1,如果想用0~255的取值范圍表示顏色,則對應的類是Color32
GetPixel介面回傳的是Color物件,我們可以通過rgb來簡單判斷一個像素是否有顏色,例:

if (color.r + color.g + color.b > 1f)
{
	// 像素有顏色
}

如果一個方塊中有顏色的像素超過了方塊的邊長samplingStep,則認為這個小方塊中央需要安排一個人,否則留空,
我們宣告一個陣列來存放點陣資料:

// 點陣
private List<Vector3> posList = new List<Vector3>();

生成點陣的邏輯如下:

// TextureFormation.cs

/// <summary>
/// 采樣梯度,梯度越小,進度越高
/// </summary>
public int samplingStep = 5;
/// <summary>
/// 坐標縮放
/// </summary>
public float scale = 1f;
/// <summary>
/// 要采樣的圖片紋理
/// </summary>
public Texture2D texture;

// ...

/// <summary>
/// 計算點陣
/// </summary>
private void CalculatePoints()
{
    if(Application.isPlaying)
    {
        if (0 != posList.Count)
            return;
    }
    else
    {
        posList.Clear();
    }
    
    var widthStep = texture.width / samplingStep;
    var heightStep = texture.height / samplingStep;
    for (int i = 0; i <= heightStep; i += samplingStep)
    {
        for (int j = 0; j <= widthStep; j += samplingStep)
        {
            // 一個block
            int colorPixelCnt = 0;
            for (int ii = 0; ii <= samplingStep; ++ii)
            {
                for (int jj = 0; jj <= samplingStep; ++jj)
                {
                    var color = texture.GetPixel(j * samplingStep + jj, i * samplingStep + ii);
                    if (color.r + color.g + color.b > 1f)
                    {
                        ++colorPixelCnt;
                    }
                }
            }
            // 有顏色的像素超數量過了方塊的邊長
            if (colorPixelCnt > samplingStep)
            {
                var pos = new Vector3(-texture.width / 2 + j * samplingStep + samplingStep / 2f, 0, -texture.height / 2 + i * samplingStep + samplingStep / 2f);
                // 對坐標進行縮放
                pos *= scale;
                posList.Add(pos);
            }
        }
    }
}

我們再提供一個獲取點陣資料的介面供外部呼叫:

// TextureFormation.cs

/// <summary>
/// 獲取點陣資料
/// </summary>
/// <returns></returns>
public IEnumerable<Vector3> EvaluatePoints()
{
    CalculatePoints();
    var rootPos = Vector3.zero;
    if (null != trans)
        rootPos = trans.position;
    for (int i = 0; i < posList.Count; ++i)
    {
        yield return rootPos + posList[i];
    }
}

為了方便在編輯器下預覽點陣,我們可以寫個OnDrawGizmos()方法,通過Gizmos來繪制幾何體,如下:

// FormationRenderer.cs

using UnityEngine;

public class FormationRenderer : MonoBehaviour
{
    private TextureFormation _formation;
    public TextureFormation Formation
    {
        get
        {
            if (_formation == null) _formation = GetComponent<TextureFormation>();
            return _formation;
        }
        set => _formation = value;
    }

    [SerializeField] private Vector3 _unitGizmoSize;
    [SerializeField] private Color _gizmoColor;

    private void OnDrawGizmos()
    {
        if (Formation == null || Application.isPlaying) return;
        Gizmos.color = _gizmoColor;

        foreach (var pos in Formation.EvaluatePoints())
        {
            Gizmos.DrawCube(transform.position + pos + new Vector3(0, _unitGizmoSize.y * 0.5f, 0), _unitGizmoSize);
        }
    }
}

效果:
請添加圖片描述
可以調節采樣梯度和坐標縮放,
在這里插入圖片描述
如下:
請添加圖片描述

七、根據點陣生成角色方陣

我們創建一個Main.cs腳本來實作這部分的邏輯,

有了點陣資料,我們就可以生成相應的角色啦,不過我們這里的每個角色都有各自的一些資訊,比如影片、速度等,這里我們封裝一個PlayerUnit類來包裝一下,

// Main.cs

public class PlayerUnit
{
    public GameObject obj;
    public Transform trans;
    public Animator ani;
    public float speed;
}

封裝一下生成角色和洗掉角色的介面,

// Main.cs

private readonly List<PlayerUnit> spawnedUnits = new List<PlayerUnit>();

// 生成角色
private void SpawnAvatar(IEnumerable<Vector3> points)
{
    foreach (var pos in points)
    {
        var unit = new PlayerUnit();
        var obj = Instantiate(unitPrefab, transform.position + pos, Quaternion.identity, parentTrans);
        unit.obj = obj;
        unit.trans = obj.transform;
        unit.ani = obj.GetComponent<Animator>();
        spawnedUnits.Add(unit);
    }
}

// 洗掉多余的角色
private void DeleteAvatar(int num)
{
    for (var i = 0; i < num; i++)
    {
        var unit = _spawnedUnits.Last();
        spawnedUnits.Remove(unit);
        Destroy(unit.obj);
    }
}

根據點陣圖生成角色,

// 根據點陣圖生成角色
private void GenFormation()
{
    points = formation.EvaluatePoints().ToList();

    if (points.Count > spawnedUnits.Count)
    {
        var remainingPoints = points.Skip(spawnedUnits.Count);
        SpawnAvatar(remainingPoints);
    }
    else if (points.Count < spawnedUnits.Count)
    {
        DeleteAvatar(spawnedUnits.Count - points.Count);
    }

    for (var i = 0; i < spawnedUnits.Count; i++)
    {
    	// 設定坐標
		unit.trans.position = points[i];
        // TODO 移動、旋轉、播影片
        
    }
}

此時的效果:
在這里插入圖片描述

八、方陣行走

我們要讓方陣跑起來,每個角色朝著自己的位置移動、旋轉,并且配套播放跑步和站立的影片,
這里需要要讓狀態過渡比較自然,我是根據距離來決定影片混合,使用線性差值來計算旋轉,代碼如下:
代碼如下:

for (var i = 0; i < spawnedUnits.Count; i++)
{
    var unit = spawnedUnits[i];
    // 距離
    var distance = Vector3.Distance(points[i], unit.trans.position);

    if (distance > unitSpeed)
    {
        // 方向
        var dir = points[i] - unit.trans.position;
        // 線性差值設定方向,朝向目標點方向
        unit.trans.forward = Vector3.Lerp(unit.trans.forward, new Vector3(dir.x, 0, dir.z), 5 * Time.deltaTime);
        // 影片混合
        unit.speed = distance > 0.8f ? distance : 0.8f;
        unit.ani.SetFloat("Speed", unit.speed);
        // 移動
        unit.trans.position = unit.trans.position + (points[i] - unit.trans.position).normalized * unitSpeed;
    }
    else
    {
    	// 距離很小,直接設定目標點位置
        unit.trans.position = points[i];
        if (unit.speed > 0)
        {
        	// 慢慢過渡為站立
            unit.speed -= Time.deltaTime * 0.5f;
            if (unit.speed < 0)
                unit.speed = 0;
            unit.ani.SetFloat("Speed", unit.speed);
        }
        // 線性差值設定方向,統一朝向正前方
        unit.trans.forward = Vector3.Lerp(unit.trans.forward, -Vector3.forward, 5 * Time.deltaTime);
    }
}

我們想點擊地面時讓整個方陣移動,這里我用了射線檢測,

if (Input.GetMouseButtonDown(0))
{
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hitInfo;
    if (Physics.Raycast(ray, out hitInfo, 200))
    {
        if ("ground" == hitInfo.collider.tag)
        {
            formation.transform.position = hitInfo.point;
        }
    }
}

其中,地面的tag設定為ground
在這里插入圖片描述
效果如下:
請添加圖片描述
如果你強行把某個角色拉到別處,她會自動乖乖跑回去站好,
請添加圖片描述

九、方陣變換

我們想要實作多個方陣的變換,需要中途切換圖片,并且可能需要設定對應的采樣梯度和坐標縮放,我這里封裝成可序列化的類,如下:

[System.Serializable]
public class TextureUnit
{
    public Texture2D texture;
    public int samplingStep;
    public float scale;
}

宣告一個public的陣列:

public TextureUnit[] textureUnits = new TextureUnit[0];

這樣就可以在Inspector面板中設定資料啦~
在這里插入圖片描述
寫個方法實作方陣變換,

// Main.cs

// 方陣變換
private void ChangeFormation()
{
    if (curTextureIndex > (textureUnits.Length - 1))
    {
        curTextureIndex = 0;
    }
    var curTextureUnit = textureUnits[curTextureIndex];
    formation.texture = curTextureUnit.texture;
    formation.samplingStep = curTextureUnit.samplingStep;
    formation.scale = curTextureUnit.scale;
    formation.ReCalculate();
}

Update中檢測空白鍵按下,如果按下則呼叫方陣變換,

// Main.cs

private int curTextureIndex = 0;

private void Update()
{
   // ...
   if (Input.GetKeyDown(KeyCode.Space))
   {
       ++curTextureIndex;
       ChangeFormation();
   }
}

效果如下:
請添加圖片描述

十、工程原始碼

本工程我已上傳到CODE CHINA,感興趣的同學可自行下載學習,
地址:https://codechina.csdn.net/linxinfa/UnityFormationsDemo
注:我使用的Unity版本為Unity 2021.1.9f1c1 (64-bit)
在這里插入圖片描述

十一、完畢

好了,就到這里吧,
我是林新發:https://blog.csdn.net/linxinfa
請添加圖片描述

原創不易,若轉載請注明出處,感謝大家~
喜歡我的可以點贊、關注、收藏,如果有什么技術上的疑問,歡迎留言或私信,我們下期見~

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296788.html

標籤:其他

上一篇:OpenCV-繪制奧運五環(帶套接效果)

下一篇:女朋友嫌我拍的照片有霧,連夜用OpenCV寫出??去霧演算法??逃過一劫(收藏保命)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more