主頁 >  其他 > [原創] 用Unity等比例制作廣州地鐵,廣州加油,早日戰勝疫情(Unity | 地鐵地圖 | 第三人稱視角)

[原創] 用Unity等比例制作廣州地鐵,廣州加油,早日戰勝疫情(Unity | 地鐵地圖 | 第三人稱視角)

2021-06-09 21:16:27 其他

文章目錄

      • 一、前言
      • 二、創建工程
        • 1、創建工程
        • 2、創建目錄
      • 三、地鐵路線地圖制作
        • 1、廣州地鐵圖
        • 2、HexTiles:六變形3D瓦片工具的基本操作
          • 2.1、HexTiles工具下載
          • 2.2、創建瓦片材質球
          • 2.3、創建瓦片容器
          • 2.4、繪制瓦片
          • 2.5、設定瓦片高度
          • 2.6、擦除瓦片
          • 2.7、瓦片材質繪制:材質替換
          • 2.8、大面積刷瓦片
          • 2.9、大面積擦除瓦片
        • 3、搭建地鐵路線
      • 四、地鐵站點制作
        • 1、地鐵站點模型
        • 2、地鐵站點材質球
        • 3、地鐵站點名稱:TextMeshPro
          • 3.1、匯入字體檔案
          • 3.2、安裝TextMeshPro
          • 3.3、制作字符集
          • 3.4、制作Font Asset
          • 3.5、顯示地鐵站名字
          • 3.6、保存站點預設
        • 4、排放地鐵站點
        • 5、地平面
      • 五、導航系統:NevMesh烘焙
        • 1、設定烘焙物件為Static
        • 2、NevMesh烘焙
      • 六、搖桿制作
        • 1、搖桿圖片
        • 2、Canvas與UICamera
        • 3、搖桿UI制作
        • 3、搖桿邏輯代碼
        • 4、掛搖桿邏腳本
        • 5、搖桿測驗
      • 七、角色、影片與控制
        • 1、角色模型下載
        • 2、影片控制器
        • 3、主角出場
        • 4、搖桿控制主角
      • 八、攝像機控制:跟隨主角與右搖桿控制旋轉
        • 1、跟隨主角
        • 2、右搖桿控制旋轉
      • 九、天空盒SkyBox與環境霧Fog
        • 1、天空盒:SkyBox
        • 2、環境霧:Fog
      • 十、登頂廣州塔
        • 1、廣州塔模型下載
        • 2、廣州塔放入場景中
        • 3、檢測主角到了廣州塔底部:觸發器
        • 4、詢問是否要上廣州塔:UI界面
        • 5、登上塔頂
        • 6、塔頂調整攝像機距離
      • 十一、功能補充
        • 1、粒子系統:煙花效果
        • 2、音樂播放:安妮的仙境
        • 3、彩蛋:天空盒道具
      • 十二、工程原始碼

一、前言

嗨,大家好,我是新發,
最近比較忙,好幾天沒寫文章了,這兩天廣州疫情的新聞頻頻上熱搜,身在廣州無時無刻不吊著個心,部分同事所在的區域已經封起來了,只能遠程上班,我住的地區暫時還比較安全,不過也已經做好遠程作業的準備了,
話說回來,我在廣州上學、生活、作業了十年了,對廣州有著特殊的情愫,
我這兩天做了一個Demo,我在Unity中搭建了整個廣州地鐵路線地圖,并做了第三人稱視角相機跟隨,雙搖桿控制,可以登上廣州塔鳥瞰整個廣州,以此獻給我熱愛的大廣州,效果如下:

注:今天廣州大規模核酸檢測,下午剛檢測完畢,回家寫這篇文章直到現在(2021-6-5 23:44),廣州加油,早日戰勝疫情!

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述
下面我將講解一下創作程序,

二、創建工程

1、創建工程

我用的Unity版本是2021.1.7f1c1 (64-bit),選擇3D模板,工程名字起為GuangzhouGogo好了,點擊創建,
在這里插入圖片描述

創建成功,
在這里插入圖片描述

2、創建目錄

養成好習慣,先規范目錄結構,創建一些檔案夾,目錄結構如下:
在這里插入圖片描述

RawAssets目錄主要是存放一些【生肉資源】或被場景依賴的資源;

注:關于【生肉資源】可以參見我之前寫的這篇文章的說明:《Unity游戲開發——新發教你做游戲(三):3種資源加載方式》

Resources目錄存放一些被代碼動態加載 資源;
Scenes目錄存放場景檔案;
Scripts目錄存放C#代碼;
ThirdPart目錄存放一些第三方工具或庫;

三、地鐵路線地圖制作

1、廣州地鐵圖

我們先找一下廣州地鐵圖,我找到的最新版本是這個:
在這里插入圖片描述
截止到2020年6月30日,廣州市已經開通的地鐵線路有14條,全市地鐵站點有213個
先把這個圖弄到Unity中,
在這里插入圖片描述

圖片格式設定為Sprite (2D and UI)
在這里插入圖片描述
把地鐵圖拖到場景中,調整坐標、旋轉、縮放,如下:
在這里插入圖片描述
效果如下:
在這里插入圖片描述

2、HexTiles:六變形3D瓦片工具的基本操作

2.1、HexTiles工具下載

地圖我想做得比較風格化,于是我找了一個六變形3D瓦片工具:HexTiles,這個工具可以在GitHub上找到,地址:https://github.com/RoryDungan/HexTiles
在這里插入圖片描述

注:2D瓦片工具可以參見我之前寫的這篇文章:《[Unity 2D] 重溫紅白機經典FC游戲,順便教你快速搭建2D游戲關卡(Tilemap | 場景 | 地圖)》

下載下來后,放入工程的ThirdPart目錄中,只需保留它的CodePlugins檔案夾即可,如下:
在這里插入圖片描述

2.2、創建瓦片材質球

我們要使用工具來繪制3D瓦片,我們需要先為瓦片制作材質球,我們先做一個綠色的材質球,在RawAssets/Materials/tiles目錄右鍵點擊選單Create/Material,創建材質球;
在這里插入圖片描述
材質球重命名為green,設定材質球的顏色為綠色,然后我們不想要有反光的效果,可以調整光滑度為0
在這里插入圖片描述
以此類推,把地鐵路線的顏色都做一個對應的材質球~
在這里插入圖片描述

2.3、創建瓦片容器

Hierarchy視圖空白處右鍵點擊選單Hex tile map,創建瓦片容器,
在這里插入圖片描述
瓦片容器上會有個HexTileMap組件,可以看到對應的功能按鈕,我們后續繪制的瓦片都會在這個Hex tile map的子節點下,
在這里插入圖片描述

2.4、繪制瓦片

確保Scene視圖的Gizmos按鈕是激活狀態的,
在這里插入圖片描述
點擊添加瓦片按鈕,把要使用的材質球拖到Material槽中,
在這里插入圖片描述
然后在場景中按住滑鼠拖動即可繪制瓦片了,在這里插入圖片描述

2.5、設定瓦片高度

我們想要在更低一層繪制瓦片,可以調整Height offset,比如我調整為-0.5,順便把材質球改成白色,
在這里插入圖片描述
現在我們繪制瓦片,可以看到是在原來的瓦片的下層繪制了,并且邊緣銜接處會自動補上,
在這里插入圖片描述

2.6、擦除瓦片

我們想把繪制的瓦片擦除,可以點擊擦除瓦片按鈕,
在這里插入圖片描述
然后在場景中點擊要擦除的瓦片,
在這里插入圖片描述

2.7、瓦片材質繪制:材質替換

點擊材質繪制按鈕,然后目標材質,
在這里插入圖片描述
然后點擊要繪制的瓦片即可,
在這里插入圖片描述

2.8、大面積刷瓦片

上面我們是一個瓦片一個瓦片刷的,我們可以調整刷子的尺寸(Brush size),比如我調整為3
在這里插入圖片描述

這樣就可以大面積刷瓦片了,
在這里插入圖片描述

2.9、大面積擦除瓦片

同樣,我們也可以大面積擦除瓦片,
在這里插入圖片描述

在這里插入圖片描述

3、搭建地鐵路線

開始沿著地鐵路線鋪路,
在這里插入圖片描述
鋪啊鋪,鋪啊鋪,
在這里插入圖片描述
把所有地鐵路線圖都鋪好,在這里插入圖片描述

四、地鐵站點制作

1、地鐵站點模型

站點就用一個簡單的柱體就好了,創建一個Cube
在這里插入圖片描述
拉長,
在這里插入圖片描述
由兩個柱體(底部和頂部)組成一個站點的模型,
在這里插入圖片描述

2、地鐵站點材質球

創建兩個材質球,分別作為站點底部和頂部的材質,
在這里插入圖片描述
將材質球賦值給上面的柱體,
在這里插入圖片描述

3、地鐵站點名稱:TextMeshPro

地鐵站點的名字我使用了TextMeshPro來顯示,它的好處是在3D空間下近距離觀察文字也是很清晰的,

注:關于TextMeshPro的使用教程可以參見我之前的這篇文章:《手把手教,Unity使用TextMeshPro顯示字體》

下面我講下操作步驟,

3.1、匯入字體檔案

找一個你喜歡的字體(TTF格式),比如我找的是免費的思源字體,
在這里插入圖片描述
將其放入Unity工程中,

在這里插入圖片描述

3.2、安裝TextMeshPro

點擊選單Window / Package,打開Package Manger視窗,
在這里插入圖片描述
Packages選擇Unity Registry,然后搜索textmeshpro,選擇TextMeshPro,點擊Install按鈕,如果你已經安裝過,則沒有Install按鈕了,
在這里插入圖片描述
安裝成功后,可以看到Window選單中多了一個TextMeshPro選單,
在這里插入圖片描述

3.3、制作字符集

我們需要為TextMeshPro創建一個字符集(一個txt檔案),把我們需要用到的字放在這個字符集檔案里,如下,在TTF同級目錄中創建一個txt檔案(characters.txt),
在這里插入圖片描述
把廣州市所有的地鐵站名字都放在這個characters.txt檔案中,
在這里插入圖片描述

3.4、制作Font Asset

點擊選單 Window / TextMeshPro / Font Asset Creator
在這里插入圖片描述
首次打開會彈出下面這個視窗,點擊Import TMP Essentials按鈕,
在這里插入圖片描述
Font Asset Creator視窗中,設定Source Font File為我們的字體TTF檔案,設定Character SetCharacters from File,設定Character File為我們的字符集檔案characters.txt,最后點擊Generate Font Atlas按鈕,
在這里插入圖片描述
此時會生成一個紋理,我們點擊Save保存,
在這里插入圖片描述
保存到RawAssets/Fonts目錄中,
在這里插入圖片描述
如下(font SDF.asset
在這里插入圖片描述

3.5、顯示地鐵站名字

在地鐵站節點下創建一個空物體,重命名為name
在這里插入圖片描述
給這個name節點添加TextMeshPro - Text組件,
在這里插入圖片描述
Text Input中輸入地鐵站的名字,比如珠江新城
設定Font Asset為我們上面生成的font SDF
在這里插入圖片描述
此時效果如下:
在這里插入圖片描述
設定一下字號,設定一下對其方式,
在這里插入圖片描述
設定一下坐標和顯示區域大小,
在這里插入圖片描述
效果如下:
在這里插入圖片描述
為了能在四個面都看得到地鐵站名字,我們再復制出另外三份,
在這里插入圖片描述
調整下坐標和旋轉角度,效果如下:
在這里插入圖片描述

3.6、保存站點預設

養成好習慣,需要重復使用的物體(模板)我們最好保存成預設,將其保存到RawAssets/Prefabs目錄中,如下:
在這里插入圖片描述

4、排放地鐵站點

按照地鐵線路,依次擺放地鐵站點,
在這里插入圖片描述
擺呀擺,
在這里插入圖片描述
終于把地鐵站全部弄好了,
在這里插入圖片描述
把站點按地鐵路線收納好,方便管理,
在這里插入圖片描述

5、地平面

創建一個Plan作為地平面,這樣影子可以投射到地面上,
在這里插入圖片描述
給地面創建一個材質球,材質球賦值給Plan
在這里插入圖片描述
調整材質球顏色,
在這里插入圖片描述

五、導航系統:NevMesh烘焙

地鐵路線有了,接下來就給它烘焙NevMesh吧,以便后面支持導航功能,

1、設定烘焙物件為Static

因為NevMesh只對場景中的靜態物件進行烘焙,所以我們需要先把地鐵路線設定為Static的,
選擇HexTileMap節點,將其設定為Static
在這里插入圖片描述
點擊Yes, change children,即所有的子節點都設定為Static
在這里插入圖片描述

2、NevMesh烘焙

點擊選單Window / AI / Navigation
在這里插入圖片描述
Navigation視窗中,點擊Bake標簽頁,
調節一下Agent Radius,因為我們的地鐵路面比較窄,所以這里的Agent Radius需要調小一點,
最后點擊Bake按鈕即可,
在這里插入圖片描述
烘焙成功后,可以看到路面上出現了藍色的網格,
在這里插入圖片描述
同時,在場景檔案目錄中,會看到生成了一個與場景同名的檔案夾,里面的NavMesh.asset保存的就是場景的導航烘焙資訊,
在這里插入圖片描述

六、搖桿制作

地圖有了,接下來就是主角了,不過在做主角之前,我們先把搖桿做一下吧~

1、搖桿圖片

搖桿的圖片很簡單,一個圓就可以了,
在這里插入圖片描述

2、Canvas與UICamera

創建一個Canvas,作為后面UI的父節點,
在這里插入圖片描述

在這里插入圖片描述

在創建一個Camera來專門渲染Canvas
在這里插入圖片描述

將其重命名為UICamera
在這里插入圖片描述

設定UICameraClear FlagsDepth only,并設定Culling MaskUI,這樣它就只會渲染UI層,把Projection設定為Orthographic(正交),
在這里插入圖片描述

接著把CanvasRender Mode(渲染模式)改為Screen Space - Camera(即由攝像機來渲染),然后把Render Camera設定為剛剛的UICamera
接著再設定下解析度適配,把Canvas Scale組件的UI Scale Mode設定為Scale with Screen Size,把解析度設定為1280, 720
在這里插入圖片描述
另外,因為UI已交給UICamera來渲染,所以Main Camera不需要再渲染UI層了,把Main CameraCulling MaskUI勾選去掉,
在這里插入圖片描述

3、搖桿UI制作

Canvas節點上右鍵點擊選單UI / Panel,創建一個Panel
在這里插入圖片描述
Image組件禁用掉,因為我們不需要Panel顯示出來,
在這里插入圖片描述
Panel下創建一個Image,重命名為leftJointedArm,作為左搖桿的父節點,
在這里插入圖片描述

設定它的錨點為bottom - left,即螢屏左下角,調整坐標和寬高,
在這里插入圖片描述
像這樣子,
在這里插入圖片描述

把它的Coloralpha調為0,因為我們只需要利用它的區域來檢測觸碰,我們不需要肉眼看見它,
在這里插入圖片描述
接著在它的子節點下創建兩個Image,分別命名為bgcenter
在這里插入圖片描述
它們的Source Image都設定為搖桿的圖片資源,
在這里插入圖片描述
分別調整下bgcenter的大小和顏色透明度,效果如下:
在這里插入圖片描述
同理再做一個右搖桿,
在這里插入圖片描述
效果如下:
在這里插入圖片描述

3、搖桿邏輯代碼

UnityUGUI提供了ScrollRect組件,非常適合用來制作搖桿,我們繼承ScrollRect然后實作OnDragOnEndDrag方法,可以很方便地獲取到搖桿的遙控資料,另外,為了檢測區域點擊,我們再實作IPointerDownHandler介面,
在這里插入圖片描述

創建搖桿腳本JointedArm.cs,
在這里插入圖片描述
JointedArm .cs代碼如下:

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System;

public class JointedArm : ScrollRect, IPointerDownHandler
{
    public Action<Vector2> onDragCb;
    public Action onStopCb;

    protected float mRadius = 0f;
    
    private Transform trans;
    private RectTransform bgTrans;
    private Camera uiCam;
    private Vector3 originalPos;

    protected override void Awake()
    {
        base.Awake();
        trans = transform;
        bgTrans = trans.Find("bg") as RectTransform;
        uiCam = GameObject.Find("UICamera").GetComponent<Camera>();
        originalPos = trans.localPosition;
    }

    void Update()
    {
        if (Input.GetMouseButtonUp(0))
        {
            //松手時,搖桿復位
            trans.localPosition = originalPos;
            this.content.localPosition = Vector3.zero;
        }
    }

    protected override void Start()
    {
        base.Start();
        //計算搖桿塊的半徑
        mRadius = bgTrans.sizeDelta.x * 0.5f;
    }

    public override void OnDrag(PointerEventData eventData)
    {
        base.OnDrag(eventData);
        var contentPostion = this.content.anchoredPosition;
        if (contentPostion.magnitude > mRadius)
        {
            contentPostion = contentPostion.normalized * mRadius;
            SetContentAnchoredPosition(contentPostion);
        }
        Debug.Log("搖桿滑動,方向:" + contentPostion);

        if(null != onDragCb)
            onDragCb(contentPostion);
    }

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);
        Debug.Log("搖桿拖動結束");
        if (null != onStopCb)
            onStopCb();
    }

    public void OnPointerDown(PointerEventData eventData)
    {
        //點擊到搖桿的區域,搖桿移動到點擊的位置
        trans.position = uiCam.ScreenToWorldPoint(eventData.position);
        trans.localPosition = new Vector3(trans.localPosition.x, trans.localPosition.y, 0);
    }
}

4、掛搖桿邏腳本

JointedArm .cs分別掛到leftJointedArmrightJointedArm上,賦值對應的center
在這里插入圖片描述

5、搖桿測驗

運行Unity,搖桿測驗效果如下:
在這里插入圖片描述

七、角色、影片與控制

1、角色模型下載

主角我在AssetStore上找到了一個心儀的模型,推薦給大家,
AssetStore地址:https://assetstore.unity.com/packages/3d/characters/humanoids/sci-fi/stylized-astronaut-114298
在這里插入圖片描述

注:更多模型下載可以參見我之前寫的這篇文章:
《Unity游戲開發——新發教你做游戲(二):60個Unity免費資源獲取網站》

將模型下載匯入Unity中,
在這里插入圖片描述

2、影片控制器

注:關于Animator組件的詳細使用可以參見我之前寫的這篇文章:《Unity影片狀態機Animator使用》

打開角色的影片控制器檔案CharacterController
在這里插入圖片描述
可以看到,兩個動作,一個idle(站立)一個Run(跑),
在這里插入圖片描述
Parameters(引數)里面有一個AnimationPar引數,這個引數就是用來控制站立與跑著兩個影片的過渡條件的,
在這里插入圖片描述
Run過渡到Idle的條件是AnimationPar等于1
在這里插入圖片描述
Idle過渡到Run的條件是AnimationPar等于0
在這里插入圖片描述

這樣,我們就可以在代碼中通過這個引數來控制影片的過渡了,例:

// public Animator anim; 

// 站立 -> 跑
anim.SetInteger("AnimationPar", 1);
// 跑 -> 站立
anim.SetInteger("AnimationPar", 0);

3、主角出場

在場景中創建一個空物體,重命名為Player
在這里插入圖片描述
把主角模型拖到Player子節點中,把主角模型也命名為Player
在這里插入圖片描述
這樣,場景中出現了我們的主角了,
在這里插入圖片描述
因為主角需要在地鐵路線上跑,我們用了導航系統NevMesh,所以主角需要掛NevMeshAgent組件,
在這里插入圖片描述
調節Radius(半徑)與Height(高度)使之與主角模型匹配,
在這里插入圖片描述
在這里插入圖片描述

4、搖桿控制主角

寫一個Player.cs腳本,主要邏輯如下,

// Player.cs 

using UnityEngine;

public class Player : MonoBehaviour
{
	public float speed = 1f;
	public float turnSpeed = 20f;
	
	public Animator anim;
	public Transform rootTrans;
	public Transform modelTrans;
	
	private bool moving = false;
	private Vector3 moveDirection = Vector3.zero;
	
	// ...
	
	void Update()
	{
	    if (moving)
	    {
	    	// 播放跑影片
	        anim.SetInteger("AnimationPar", 1);
			// 更新主角坐標
	        rootTrans.position += moveDirection * speed * Time.deltaTime;
	        // 更新主角朝向,使用Vector3.Lerp進行插值運算,使得角度變化不那么生硬
	        modelTrans.forward = Vector3.Lerp(modelTrans.forward, moveDirection, turnSpeed * Time.deltaTime);
	    }
	    else
	    {
	    	// 播放站立影片
	        anim.SetInteger("AnimationPar", 0);
	    }
	}
	
	// 移動
	public void Move(Vector3 direction)
	{
	    moveDirection = direction;
	    moving = true;
	}
	
	// 站立
	public void Stand()
	{
	    moving = false;
	}
	
	// ...
}

將腳本掛到Player父節點上,賦值對應的變數,
在這里插入圖片描述
為了方便管理,我們再封裝一個游戲管理器GameMgr.cs,由游戲管理器來調度搖桿與主角,

// GameMgr.cs

public Player player;
// 左搖桿
public JointedArm leftJointedArm;
// 攝像機的Transform
private Transform camTrans;

// ...

leftJointedArm.onDragCb = (direction) =>
	{
		// 搖桿向量轉世界坐標系下的向量
	    var realDirect = camTrans.localToWorldMatrix * new Vector3(direction.x, 0, direction.y);
	    realDirect.y = 0;
	    // 向量歸一化
	    realDirect = realDirect.normalized;
	    // 主角根據向量移動
	    player.Move(realDirect);
	};
leftJointedArm.onStopCb = () => { player.Stand(); };

注:從搖桿的2D向量轉換為控制主角的3D向量,這里我用了一個矩陣變換,camTrans.localToWorldMatrix,相當于把相對于攝像機的區域坐標轉換為世界坐標,

這樣我們的搖桿就可以控制主角移動了,不過現在攝像機并不會跟著主角移動,所以下一步我們就來做攝像機跟隨吧~
在這里插入圖片描述

八、攝像機控制:跟隨主角與右搖桿控制旋轉

1、跟隨主角

攝像機需要始終看著主角,我們可以使用TransformLookAt方法;
攝像機要跟著主角移動,就是根據主角當前的坐標來設定攝像機的坐標,我們可以使用Transformposition屬性,
創建一個CameraControler.cs腳本,實作攝像機控制的邏輯,

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

// 攝像機控制
public class CameraControler : MonoBehaviour
{
	// 攝像機看向的物體
	public Transform lookAt;
	// 攝像機自身的Transform
    public Transform camTransform;
    // 攝像機與目標物體的距離
    public float distance = 1.2f;
	
	private float currentX = 0.0f;
    private float currentY = 20.0f;
	
	// ...
	
	private void Start()
    {
        camTransform = transform;
    }

	private void LateUpdate()
    {
        Vector3 dir = new Vector3(0, 0, -distance);
        Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
        camTransform.position = lookAt.position + rotation * dir;
        camTransform.LookAt(lookAt.position);
    }
	
	// ...
}

CameraControler.cs掛到攝像機上,賦值對應的變數,這樣攝像機就可以跟著主角移動了,
在這里插入圖片描述

2、右搖桿控制旋轉

CameraControler.cs腳本中加上旋轉的邏輯,

// CameraControle.cs

// 旋轉速度
public float rotateSpeed = 0.01f;
private bool rotating;
// 旋轉偏量
private Vector2 rotateDelta;

// 限制旋轉范圍
private const float Y_ANGLE_MIN = 10f;
private const float Y_ANGLE_MAX = 50.0f;

private void Update()
{
    if (rotating)
    {
    	// 限制旋轉范圍
        currentX += rotateDelta.x;
        currentY += rotateDelta.y;
        currentY = Mathf.Clamp(currentY, Y_ANGLE_MIN, Y_ANGLE_MAX);
    }
}

// 設定旋轉偏量
public void RotateCam(Vector2 delta)
{
    rotateDelta = delta * rotateSpeed;
    rotating = true;
}

// 停止旋轉
public void StopRotate()
{
    rotating = false;
}

private void LateUpdate()
{
    Vector3 dir = new Vector3(0, 0, -distance);
    Quaternion rotation = Quaternion.Euler(currentY, currentX, 0);
    // 設定相機坐標
    camTransform.position = lookAt.position + rotation * dir;
    // 設定相機角度看向目標物體
    camTransform.LookAt(lookAt.position);
}

// ..

GameMgr.cs中添加右搖桿與相機旋轉的調度,

// GameMgr.cs

public JointedArm rightJointedArm;
public CameraControler camCtrler;

// ...
rightJointedArm.onDragCb = (direction) =>
	{
	    camCtrler.RotateCam(direction);
	};
rightJointedArm.onStopCb = () => { camCtrler.StopRotate(); };

最后記得給GameMgr.cs賦值對應的變數,
在這里插入圖片描述
右搖桿效果如下:
在這里插入圖片描述

九、天空盒SkyBox與環境霧Fog

1、天空盒:SkyBox

現在天空比較單一,我們加上天空盒的效果,
天空盒的資源我是在AssetStore上下載的,地址:https://assetstore.unity.com/packages/2d/textures-materials/sky/farland-skies-cloudy-crown-60004

在這里插入圖片描述
下載下來,匯入到Unity工程中,
在這里插入圖片描述

只需要把天空盒的材質球拖到場景中即可生效,或者選單Window / Rendering / Lighting
在這里插入圖片描述
點擊Environment,然后設定Skybox Material為對應的天空盒材質球即可,
在這里插入圖片描述
我喜歡Sunset(日落)的天空效果,加上之后效果如下,是不是一下子就唯美了很多:
在這里插入圖片描述
我們也可以通過代碼設定天空盒,例:

RenderSettings.skybox = skyMat;

可以再欣賞下其他不同天空盒的效果:
清晨:
在這里插入圖片描述
中午:
在這里插入圖片描述

晚霞:
在這里插入圖片描述
午夜:
在這里插入圖片描述

2、環境霧:Fog

不同的天空盒,需要搭配不同顏色的環境霧效,
Lighting視窗的Environment標簽頁中即可開啟環境霧,如下:
我們可以設定霧效的顏色、密度等引數,
在這里插入圖片描述
我們可以對比下 沒霧效有霧效的區別:在這里插入圖片描述

十、登頂廣州塔

大家應該都知道廣州的地標建筑物:廣州塔(小蠻腰),必須安排上,

1、廣州塔模型下載

我找到了廣州塔的模型,模型下載地址:https://www.3dxy.com/3dmodel/148664.html
下載FBX格式的,匯入Unity工程的RawAssets/Models目錄中,
在這里插入圖片描述
在這里插入圖片描述

2、廣州塔放入場景中

把廣州塔模型放入場景中,調整坐標到對應的位置,調整模型縮放,效果如下:
在這里插入圖片描述

3、檢測主角到了廣州塔底部:觸發器

我用了觸發器來檢測主角是否到了廣州塔底部,在廣州塔底部創建一個物體,并掛上BoxCollider組件,調整碰撞體大小,如下:
在這里插入圖片描述
在這里插入圖片描述
把碰撞體的Is Trigger勾選上,這樣它就是一個觸發器了,
在這里插入圖片描述
想要檢測主角是否進入了觸發器中,還需要給主角也掛上碰撞體(Collider)和剛體(Rigidbody),給主角安排上,因為我們不需要模擬重力,所以Use Gravity不要勾選,
在這里插入圖片描述
在這里插入圖片描述
調整碰撞體大小的時候,如果看不清楚,可以把Scene視圖的Shading Mode設定為Wireframe(線框),
在這里插入圖片描述
這樣就可以比較清楚得看到碰撞體了,
在這里插入圖片描述
接著寫個廣州塔觸發器腳本CantonTowerTrigger.cs

using UnityEngine;

/// <summary>
/// 廣州塔觸發器
/// </summary>
public class CantonTowerTrigger : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
		// 進入了觸發器
    }

    private void OnTriggerExit(Collider other)
    {
		// 離開了觸發器
    }
	
	// ...
}

CantonTowerTrigger.cs腳本掛到觸發器上,
在這里插入圖片描述
畫成圖是這樣子:
在這里插入圖片描述

4、詢問是否要上廣州塔:UI界面

主角進入廣州塔觸發器時,彈出UI界面詢問是否要上廣州塔,
我們先做個詢問的UI界面,
在這里插入圖片描述
層級結構如下:
在這里插入圖片描述
把界面保存為預設,放在Resources目錄中,這樣我們就可以通過Resources.Load來加載界面資源了,
封裝一個界面管理器,方便界面的顯示與關閉,封裝一個界面基類BaseUIPanel,所有的界面都繼承這個基類,畫成關系圖是這樣子,
在這里插入圖片描述
界面管理器和界面基類代碼如下:

using System.Collections.Generic;
using UnityEngine;

// 界面管理器
public class UIPanelMgr
{
    public void Init()
    {
        canvas = GameObject.Find("Canvas").transform;
    }

    public void ShowPanel(string panelName)
    {
        var panel = GetPanelRes(panelName);
        if(null != panel)
            panel.Show();
    }

    public void HidePanel(string panelName)
    {
        if (!panels.ContainsKey(panelName))
            return;

        panels[panelName].Hide();
    }

    private BaseUIPanel GetPanelRes(string panelName)
    {
        if (panels.ContainsKey(panelName))
            return panels[panelName];
        var prefab = Resources.Load<GameObject>(panelName);
        var go = Object.Instantiate(prefab);
        go.transform.SetParent(canvas, false);
        var panel = go.GetComponent<BaseUIPanel>();
        panels.Add(panelName, panel);
        return panel;
    }

    private Dictionary<string, BaseUIPanel> panels = new Dictionary<string, BaseUIPanel>();
    private Transform canvas;

    private static UIPanelMgr s_instance;
    public static UIPanelMgr instance
    {
        get
        {
            if (null == s_instance)
                s_instance = new UIPanelMgr();
            return s_instance;
        }
    }
}

// 界面基類
public class BaseUIPanel : MonoBehaviour
{
    protected GameObject panelObj;

    protected void Awake()
    {
        panelObj = gameObject;
    }

    public virtual void Show()
    {
        panelObj.SetActive(true);
    }

    public virtual void Hide()
    {
        panelObj.SetActive(false);
    }
}

然后寫一個詢問是否上廣州塔的界面類GoCantonTowerPanel .cs,它繼承BaseUIPanel,代碼如下,

using UnityEngine.UI;

public class GoCantonTowerPanel : BaseUIPanel
{
    public Button noBtn;
    public Button okBtn;

    private void Start()
    {
        noBtn.onClick.AddListener(Hide);
        okBtn.onClick.AddListener(() => 
        {
            // TODO:前往廣州塔頂部
		
            Hide();
        });
    }
}

把腳本掛到界面根節點上,并賦值按鈕物件,
在這里插入圖片描述
回到廣州塔觸發器中,補上顯示界面的呼叫,

// CantonTowerTrigger.cs

// 廣州塔觸發器

private void OnTriggerEnter(Collider other)
{
    UIPanelMgr.instance.ShowPanel("GoCantonTowerPanel");
}

private void OnTriggerExit(Collider other)
{
    UIPanelMgr.instance.HidePanel("GoCantonTowerPanel");
}

這樣,我們就實作了經過廣州塔底部地時候彈出詢問框的功能了,效果如下:
在這里插入圖片描述

5、登上塔頂

點擊前往按鈕,主角要移動到塔頂,我們可以事先在塔頂創建一個空物體,作為一個定位,主角瞬間移動到這個位置即可,
在這里插入圖片描述

同理,我們也在塔底放一個空物體,作為從塔上下來時的定位,

在這里插入圖片描述
界面邏輯中如果直接操作Player類不是很合適,我們封裝一個事件管理器,通過拋事件來解耦,補上前往按鈕的點擊邏輯,

// GoCantonTowerPanel.cs

okBtn.onClick.AddListener(() => 
     {
         // 前往廣州塔頂部
         EventDispatcher.instance.DispatchEvent(EventDef.GO_TO_CANTONTOWER_TOP);
         UIPanelMgr.instance.ShowPanel("OnTopCantonTowerPanel");
         Hide();
     });

主角類中實作去塔頂的邏輯,

// Player.cs

/// <summary>
/// 去廣州塔頂部
/// </summary>
public void GoToCantonTowerTop(Transform towerTop)
{
    canMove = false;
    navAgent.enabled = false;
    rootTrans.position = towerTop.position;
    rootTrans.forward = towerTop.forward;
}

效果如下:
在這里插入圖片描述

6、塔頂調整攝像機距離

在塔頂鳥瞰廣州,再做一個可以拉長鏡頭的功能,
這個功能就是在攝像機控制器CameraControler.cs中修改distance的值,也是通過事件來觸發,回應函式如下:

// CameraControler.cs

private void OnEventChangeCamDistance(params object[] args)
{
    var offset = (float)args[0];
    distance = originalDistance + offset * 20f;
}

在這里插入圖片描述

十一、功能補充

1、粒子系統:煙花效果

用粒子系統做個煙花效果,
在這里插入圖片描述
用到的粒子圖片如下,比較簡單,可以自行用PhotoShop制作:
在這里插入圖片描述
粒子引數如下:
在這里插入圖片描述
在這里插入圖片描述

注:關于粒子系統的教程,可以參見我之前寫的這些文章:
《學Unity的貓——第十五章:Unity粒子系統ParticleSystem,下雪啦下雪啦》
《Unity使用ShaderGraph配合粒子系統,制作子彈拖尾特效(Fate/stay night金閃閃的大招效果)》
《手把手教你使用Unity制作一個飛機噴射火焰尾氣的粒子效果》

在場景中克隆幾個煙花粒子,用于回圈復用,
在這里插入圖片描述
寫個煙花腳本,實作隨機坐標播放粒子的功能,

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

[RequireComponent(typeof(ParticleSystem))]
public class Fireworks : MonoBehaviour
{
    private ParticleSystem particle;
    private Transform trans;

    void Start()
    {
        trans = transform;
        particle = GetComponent<ParticleSystem>();
        StartCoroutine(RandomLoopFireworks());
    }

    IEnumerator RandomLoopFireworks()
    {
        while (true)
        {
            if (particle.isPlaying)
                yield return null;

            // 隨機坐標
            trans.position = new Vector3(Random.Range(-20, 20), Random.Range(8, 15), Random.Range(-20, 20));
            particle.Play();

            yield return new WaitForSeconds(Random.Range(0.3f, 1.5f));
        }
    }
}

效果如下:
在這里插入圖片描述

2、音樂播放:安妮的仙境

廣州地鐵站的經典背景音樂:安妮的仙境,匯入到工程中,
在這里插入圖片描述
GameMgr掛上音源Audio Source組件,賦值Audio Clip安妮的仙境,勾選Play On Awake,這樣一啟動就會自動播放,勾選Loop,這樣背景音樂就可以回圈播放了,
在這里插入圖片描述

3、彩蛋:天空盒道具

我把天空盒做成了道具,碰到道具可以動態切換天空盒,原理也是用的觸發器,
在這里插入圖片描述

十二、工程原始碼

本工程原始碼已上傳到CodeChina,感興趣的同學可自行下載學習,
地址:https://codechina.csdn.net/linxinfa/GuangzhouGogo
注:我使用的Unity版本:Unity 2021.1.7f1c1 (64-bit)
在這里插入圖片描述
注:本工程僅供學習使用,未經授權不得用于商業用途!
在這里插入圖片描述

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

標籤:其他

上一篇:C++11標準下的單例設計模式

下一篇:6步教你封殺惡意登錄服務器的ip

標籤雲
其他(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