目錄
游戲原型
- 游戲玩法:在有界的戰場上,玩家將駕駛坦克,代表綠色陣營,與你的隊友一起擊潰紅藍陣營的敵人,在這場三方大戰中奪得勝利! - 操作指南: - 移動:WASD - 開火:Space - 第一/第三人稱視角轉換:PgDn - 第三人稱下的視角轉動:← →項目演示
Github項目地址:3D坦克大戰 TankBattle
繪圖資源
主要素材來源於官方[Tanks教程](https://learn.unity.com/project/tanks-tutorial)中的[Tanks!Tutorial素材包](https://assetstore.unity.com/packages/essentials/tutorial-projects/tanks-tutorial-46209)- 戰場搭建:直接使用素材包內的LevelArt即可,當然也可在此基礎上修改、擴展
- 玩家:
- 物體:選用素材包內綠色坦克模型作為Player,除了模型外還包含子物體:發射點ShootPoint,第一人稱攝像機FirstCamera,血條畫布HealthCanvas
- 組件/腳本掛載:AudioSource,Tank.cs,TankWeapon.cs
- 敵人/隊友:
- 物體:除了模型外還包含子物體血條畫布HealthCanvas
- 組件/腳本掛載:AudioSource,NavMeshAgent,AITank.cs,TankWeapon.cs
- 相機:默認開局為第三人稱視角
- ThirdCamera:采用Orthographic模式,作為TankCamera的子物體,在TankCamera掛載TankCamera.cs腳本進行控制
- FirstCamera:采用Perspective模式,作為玩家坦克Player的子物體,調整適當位置及角度
- 陣營:
- 創建Layer:Ground、Players、Blue、Green、Red,並對應設置
- 將創建多個敵人歸並於各自陣營的空物體下,本例為BlueEnemy,RedEnemy,GreenEnemy
- UI:
- 全局UI:建立Canvas,用於顯示屏幕左下角玩家血量,及左側操作指導,此外還包括死亡、勝利等UI
- 坦克外圍血條UI:新建HealthCanvas,包含血量背景條Health Background及實時血條HealthSlider(素材均來自官方包內)。后將HealthCanvas設於各方坦克預制體下,調整合適大小、高度及顯示方式
- 其他:
- 背景音樂:另設空物體BackGroundMusic添加AudioSource,開始時即循環播放
- GameManager空物體:掛載GameManager.cs及全局UI的腳本UI.cs
- 導航網絡烘培:Window->AI->navigation內設置
- 坦克殘骸:另取坦克模型保留基本的物件,修改為灰暗色,修改BoxCollider保持間隔不相互碰撞,添加素材包內TankExplosion爆炸特效。死亡后實現爆沖力將各部件被沖散
代碼實現
腳本名 | 掛載於 | 功能 |
---|---|---|
shell.cs | 炮彈Shell預制體 | 實現發射的炮彈的爆炸(特效,沖擊力,銷毀炮彈) |
TankWeapon.cs | 所有坦克的預制體 | 實現坦克發射炮彈的過程(實例化炮彈,賦予初速度,開火聲,炮彈冷卻) |
Tank.cs | 玩家Player | 實現玩家與坦克的交互(前后左右移動,空格開火) |
TankCamera.cs | TankCamera | 實現第三人視角跟隨玩家坦克移動,且還進行第一/第三人稱視角的切換控制 |
Unit.cs | 作為Tank.cs和AItank.cs的父類 | 實現所有坦克的基本屬性(陣營,血量,死亡爆炸特效,傷害計算) |
AITank.cs | 除玩家外的所有坦克預制體 | 實現npc坦克的功能(設置陣營、搜索敵人、自動導航、攻擊、自身血條UI) |
UI.cs | GameManager | 實現主界面下玩家的血條UI及玩家坦克外圍的血條UI,勝利及失敗UI,此外還有勝利判定 |
LayerManager.cs | 設置靜態方法供其他腳本調用 | 實現設置陣營(設置Layer)的函數 |
GameManager.cs | GameManager | 判定玩家是否死亡,若死亡則重置游戲 |
技術探討
**1.炮彈實現射出的方法**: - 賦予炮彈初速度:`ShellRigidbody.velocity = shootPoint.forward * shootPower;`,(本例方案) - 施加力:`ShellRigidbody.AddForce(shootPoint.forward * shootPower * 50f);`2.開火時炮彈的實例化位置:
- 產生問題:運動中開火時,實例化的炮彈與自身碰撞
- 問題分析:炮彈發射機理就是炮彈shell在炮口前一定位置實例化並賦予初速度,但是坦克也存在移動,因此假若距離較近,坦克移動速度較快時,容易造成實例化的炮彈立即與自身碰撞
- 解決方案:需要留意位置調整、角度及坦克運動速度,本例實例化炮彈位置即為shootPoint的position
3.AI坦克對敵判定
- 產生問題:原思路想采用射線檢測來判定前面一定范圍是否存在敵人,即
if (hit.collider.gameObject.layer == enemy.layer)
,但現象是:敵人/隊友是否開火呈隨機發生,無規律 - 問題分析:射線檢測到的一直是tank上的部件,而那些部件物體不是enemy,if不滿足無法進行射擊
- 解決方案:在AITank.cs腳本內另設SearchEnemy()函數,功能是搜索返回距離自己最近的敵人;在Update內首先導航跟蹤這個敵人,然后判斷當這個搜索到的敵人在開火范圍內即可開火,否則重新SearchEnemy(),詳細描述見腳本內注釋
4.AI坦克導航:
- 產生問題:敵人及隊友坦克的NavMeshAgent導航混亂
- 問題分析:很大原因在於導航網絡的烘培,及NavMeshAgent的參數設置
- 解決方案:方法就是合理設置Navigation內的各項參數及NavMashAgent上的參數,也可直接采用官方教程視頻內的參數
5.第一人稱視角:
- 產生問題:玩家在第一人稱視角下被銷毀是報錯,第一人稱視角消失,再無法切換視角
- 問題分析:FirstCamera掛載於Player,當玩家死亡時Player銷毀,造成FirstCamera的銷毀
- 解決方案:在TankCamera.cs內添加判定,若玩家不存在則啟用第三人稱視角相機
- 理想方案:兩個視角的相機都掛載在物體TankCamera上,統一由本腳本使用;FirstCamera不僅跟隨Player正常移動、旋轉,且不會在玩家死亡時銷毀;該方案暫未較好實現