第一篇:unity3d使用說明
Unity3D中的預制件(Prefab)的創建和使用說明!!!
首先我說明一下什么預制件?
在U3D里面我們叫它Prefab;我們可以這樣理解:當制作好了游戲組件(場景中的任意一個gameobject),我們希望將它制作成一個組件模版,用于批量的套用工作,例如說場景中本質上“重復”的東西,“敵人”,“士兵”,“子彈”。。。。。。這里說本質是因為默認生成的prefab其實和模版是一模一樣的,就像是克隆體,但生成的位置和角度以及生成后的一些屬性是允許發生變化的。
如何制作Prefab?
首先創建一個prefab的文件夾吧~
接著我在場景中創建一個備選預制件組件,這里就直接創建一個cube好了
這里有兩種方法將這個cube變更為預制件
1.直接將cube拖拽到_Prefabs的文件夾里。(真的超簡單)
2.先在_Prefabs的文件夾里創建一個預制件
接著將cube拓展到這個預制件上面。
現在看看場景中的cube可以在inspector面板中看到多了這樣一欄,點擊select可以定位到project中的預制件模版“母體”,revert就是還原當前預制件,apply就是確定當前預制件羅~好吧,我不想把各位當成傻瓜,有興趣可以自己動手試試他們的作用。
如何在場景中創建預制件?
創建一個腳本,好吧~
寫一個暴露變量用于記錄預制件的“母體”
接著在鼠標點擊時創建,我這里創建的位置和旋轉都為0。
現在布置一下腳本和變量:
運行點擊屏幕:
可以注意到場景的面板中創建了很多的“克隆體”。
第二篇:總結使用Unity3D優化游戲運行性能的經驗
流暢的游戲玩法來自流暢的幀率,而我們即將推出的動作平臺游戲《Shadow Blade》已經將在標準iPhone和iPad設備上實現每秒60幀視為一個重要目標。
以下是我們在緊湊的優化過程中提升游戲運行性能,并實現目標幀率時需要考慮的事項。--來自狗刨學習網
當基本游戲功能到位時,就要確保游戲運行表現能夠達標。我們衡量游戲運行表現的一個基本工具是Unity內置分析器以及Xcode分析工具。使用Unity分析器來分析設備上的運行代碼真是一項寶貴的功能。
我們總結了這種為將目標設備的幀率控制在60fps而進行衡量、調整、再衡量過程的中相關經
一、遇到麻煩時要調用“垃圾回收器”(Garbage Collector,無用單元收集程序,以下簡稱GC)
由于具有C/C++游戲編程背景,我們并不習慣無用單元收集程序的特定行為。確保自動清理你不用的內存,這種做法在剛開始時很好,但很快你就公發現自己的分析器經常顯示CPU負荷過大,原因是垃圾回收器正在收集垃圾內存。這對移動設備來說尤其是個大問題。要跟進內存分配,并盡量避免它們成為優先數,以下是我們應該采取的主要操作:
1.移除代碼中的任何字符串連接,因為這會給GC留下大量垃圾。
2.用簡單的“for”循環代替“foreach”循環。由于某些原因,每個“foreach”循環的每次迭代會生成24字節的垃圾內存。一個簡單的循環迭代10次就可以留下240字節的垃圾內存。
3.更改我們檢查游戲對象標簽的方法。用“if (go.CompareTag (“Enemy”)”來代替“if (go.tag == “Enemy”)” 。在一個內部循環調用對象分配的標簽屬性以及拷貝額外內存,這是一個非常糟糕的做法。
4.對象庫很棒,我們為所有動態游戲對象制作和使用庫,這樣在游戲運行時間內不會動態分配任何東西,不需要的時候所有東西反向循環到庫中。
5.不使用LINQ命令,因為它們一般會分配中間緩器,而這很容易生成垃圾內存。
二、謹慎處理高級腳本和本地引擎C++代碼之間的通信開銷。
所有使用Unity3D編寫的游戲玩法代碼都是腳本代碼,在我們的項目中是使用Mono執行時間處理的C#代碼。任何與引擎數據的通信需求都要有一個進入高級腳本語言的本地引擎代碼的調用。這當然會產生它自己的開銷,而盡量減少游戲代碼中的這些調用則要排在第二位。
1.在這一情景中四處移動對象要求來自腳本代碼的調用進入引擎代碼,這樣我們就會在游戲玩法代碼的一個幀中緩存某一對象的轉換需求,并一次僅向引擎發送一個請求,以便減少調用開銷。這種模式也適用于其他相似的地方,而不僅局限于移動和旋轉對象。
2.將引用本地緩存到元件中會減少每次在一個游戲對象中使用 “GetComponent” 獲取一個元件引用的需求,這是調用本地引擎代碼的另一個例子。
三、物理效果
1.將物理模擬時間步設置到最小化狀態。在我們的項目中就不可以將讓它低于16毫秒。
2.減少角色控制器移動命令的調用。移動角色控制器會同步發生,每次調用都會耗損極大的性能。我們的做法是緩存每幀的移動請求,并且僅運用一次。
3.修改代碼以免依賴“ControllerColliderHit” 回調函數。這證明這些回調函數處理得并不十分迅速。
4.面對性能更弱的設備,要用skinned mesh代替physics cloth。cloth參數在運行表現中發揮重要作用,如果你肯花些時間找到美學與運行表現之間的平衡點,就可以獲得理想的結果。
5.在物理模擬過程中不要使用ragdolls,只有在必要時才讓它生效。
6.要謹慎評估觸發器的“onInside”回調函數,在我們的項目中,我們盡量在不依賴它們的情況下模擬邏輯。
7.使用層次而不是標簽。我們可以輕松為對象分配層次和標簽,并查詢特定對象,但是涉及碰撞邏輯時,層次至少在運行表現上會更有明顯優勢。更快的物理計算和更少的無用分配內存是使用層次的基本原因。
8.千萬不要使用Mesh對撞機。
9.最小化碰撞檢測請求(例如ray casts和sphere checks),盡量從每次檢查中獲得更多信息。
四、讓AI代碼更迅速
我們使用AI敵人來阻攔忍者英雄,并同其過招。以下是與AI性能問題有關的一些建議:
1.AI邏輯(例如能見度檢查等)會生成大量物理查詢??梢宰孉I更新循環設置低于圖像更新循環,以減少CPU負荷。
五、最佳性能表現根本就不是來自代碼!
沒有發生什么情況的時候,就說明性能良好。這是我們關閉一切不必要之物的基本原則。我們的項目是一個側邊橫向卷軸動作游戲,所以如果不具有可視性時,就可以關閉許多動態關卡物體。
1.使用細節層次的定制關卡將遠處的敵人AI關閉。
2.移動平臺和障礙,當它們遠去時其物理碰撞機也會關閉。
3.Unity內置的“動畫挑選”系統可以用來關閉未被渲染對象的動畫。
4.所有關卡內的粒子系統也可以使用同樣的禁用機制。
六、回調函數!那么空白的回調函數呢?
要盡量減少Unity回調函數。即使敵人回調函數存在性能損失。沒有必要將空白的回調函數留在代碼庫中(有時候介于大量代碼重寫和重構之間)。
七、讓美術人員來救場
在程序員抓耳撓腮,絞盡腦汁去想該如何讓每秒運行更多幀時,美術人員總能神奇地派上大用場。
1.共享游戲對象材料,令其在Unity中處于靜止狀態,可以讓它們綁定在一起,由此產生的簡化繪圖調用是呈現良好移動運行性能的重要元素。
2.紋理地圖集對UI元素來說尤其有用。
3.方形紋理以及兩者功率的合理壓縮是必不可少的步驟。
4.我們的美術人員移除了所有遠處背景的網格,并將其轉化為簡單的2D位面。
5.光照圖非常有價值。
6.我們的美術人員在一些關口移除了額外頂點。
7.使用合理的紋理mip標準是一個好主意(注:要讓不同分辨率的設備呈現良好的幀率時尤其如此)。
8.結合網格是美術人員可以發揮作用的另一個操作。
9.我們的動畫師盡力讓不同角色共享動畫。
10.要找到美學/性能之間的平衡,就免不了許多粒子效果的迭代。減少發射器數量并盡量減少透明度需求也是一大挑戰。
八、要減少內存使用
使用大內存當然會對性能產生負面影響,但在我們的項目中,我們的iPod由于超過內存上限而遭遇了多次崩潰事件。我們的游戲中最耗內存的是紋理。
1.不同設備要使用不同的紋理大小,尤其是UI和大型背景中的紋理?!禨hadow Blade》使用的是通用型模板,但如果在啟動時檢測到設備大小和分辨率,就會載入不同資產。
2.我們要確保未使用的資產不會載入內存。我們必須遲一點在項目中找到僅被一個預制件實例引用,并且從未完全載入內存中實例化的資產。
3.去除網格中的額外多邊形也能實現這一點。
4.我們應該重建一些資產的生周期管理。例如,調整主菜單資產的加載/卸載時間,或者關卡資產、游戲音樂的有效期限。
5.每個關卡都要有根據其動態對象需求而量身定制的特定對象庫,并根據最小內存需求來優化。對象庫可以靈活一點,在開發過程中包含大量對象,但知道游戲對象需求后就要具體一點。
6.保持聲音文件在內存的壓縮狀態也是必要之舉。
加強游戲運行性能是一個漫長而具有挑戰性的過程,游戲開發社區所分享的大量知識,以及Unity提供的出色分析工具為《Shadow Blade》實現目標運行性能提供了極大幫助。
第三篇:Unity3D編寫雷電游戲
基礎實用的一篇經驗教程!
一、搭建游戲的框架。
一般的游戲都可以分為四個場景:
1.開始界面
2.游戲場景
3.暫停界面
4.結束界面
開始界面,就是存放開始菜單的地方了,游戲場景就是游戲的主場景,游戲的主要元素都在這邊體現,暫停和結束畫面我就不多說了。更多的還有在開始和主游戲場景之間加入過場動畫等等。當然你也可以在暫停界面中插入廣告
我們會發現這幾個場景之間其實就是切換來切換去的關系。如果知道設計模式中的State模式,就會發現跟這個很象??梢酝ㄟ^State模式來實現這幾個場景的分離,然后分邊為他們添加不同的元素。
想要掛接在Unity3D中的結點的腳本都得繼承MonoBehaviour,State就是所有的狀態的父類了,主要是三個函數,Init()用于這個狀態的初始化,Update用于場景的更新,Exit()用于當離開當前狀態時所進行的一些操作,比如隱藏當前界面等。
創建一個空的Object用來掛接我們游戲的主腳本,代碼如下:
using UnityEngine; using System.Collections; public class Main_Script : MonoBehaviour { public State m_CurState; public void ChangeState(State newState) { m_CurState.Exit(); m_CurState = newState; m_CurState.Init(); } // Use this for initialization void Start () { m_CurState.Init(); } // Update is called once per frame void Update ()
{ m_CurState.Update(); } } 這樣我們就可以輕松的在不同的狀態中切換了。想要增加一個新的狀態,就只需繼承State類,然后在其中寫這個狀態所要的元素,在適當的地方ChangeState一下就好了。
腳本的層次結構如下: 例如我在按鈕按下時切換到開始場景:
using System.Collections; public class BeginGame : MonoBehaviour { public StateRun m_RunState; public Main_Script m_MainScript; // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnMouseEnter() { print("enter"); } void OnMouseUp() { m_MainScript.ChangeState(m_RunState); } void OnMouseExit() { print("exit"); } } 這個腳本是掛在一個板上面的,點擊它時就進入游戲的主場景了。下回說一下飛機的移動。
現在開始真正的游戲元素的編寫了。
第一步,讓飛機動起來。
首先是飛機的前進,通常2D中的做就是背景的循環滾動。
在3D中我們可以讓攝像機移動,背景我們可以做超一個大地形。。在地形上擺一些固定的東西。
// Update is called once per frame void Update () { TurnLeft = false; TurnRight = false; if (Input.GetKey(KeyCode.W)) {
Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); //print(screenPos.y); if (Screen.height > screenPos.y) this.transform.Translate(Vector3.forward * Time.deltaTime * m_nMoveSpeed); } if (Input.GetKey(KeyCode.S)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (0 < screenPos.y) this.transform.Translate(Vector3.forward * Time.deltaTime * -m_nMoveSpeed); } if (Input.GetKey(KeyCode.A)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (0 < screenPos.x) this.transform.Translate(Vector3.left * Time.deltaTime * m_nMoveSpeed); //向左轉
if (CurRotation < RotateLimit) { print(CurRotation); CurRotation += RotateSpeed; } TurnLeft = true; } if (Input.GetKey(KeyCode.D)) { Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); if (Screen.width > screenPos.x) this.transform.Translate(Vector3.left * Time.deltaTime * -m_nMoveSpeed); //向右轉
if (CurRotation > -RotateLimit) CurRotation -= RotateSpeed; TurnRight = true; } //回歸
if (!TurnLeft && !TurnRight) { if (CurRotation > 0.0) CurRotation -=RotateSpeed; else if (CurRotation < 0) CurRotation +=RotateSpeed; } Quaternion rot = Quaternion.AngleAxis(CurRotation, new Vector3(0, 0, 1)); m_Plane.rotation = rot;
//讓相機和飛機一起以一定的速度前移
this.transform.Translate(Vector3.forward * Time.deltaTime * m_nMoveSpeed); Camera.mainCamera.transform.Translate(Vector3.up * Time.deltaTime * m_nMoveSpeed); } 飛機的主要控制代碼。。不知為什么,我的兩個角度限制沒有效果。。郁悶。。有空還看一下。。
這次先加入子彈的發射吧,沒用模型,先用的一個capsule的prefab代替吧。
一想到各種武器之間的隨意切換,就不由的想到了設計模式中的Strategy模式。
有關策略模式的詳細介紹可以通過百度和維基來學習。
這個模式其實和State模式差不多。
Weapon類是所有武器的基類,新的武器繼承于它,設置發射點,子彈模型,然后實現Fire函數就可以了。
WeaponManager用于管理所有武器,切換武器。
using UnityEngine; using System.Collections; public class WeaponManager : MonoBehaviour { public Weapon m_CurWeapon; private float m_FireElapseTime = 0;
// Use this for initialization void Start () { } // Update is called once per frame void Update () { m_FireElapseTime += Time.deltaTime; if (Input.GetKey(KeyCode.Space)) { if ( m_FireElapseTime > m_CurWeapon.GetBulletInterval()) { m_CurWeapon.Fire(); m_FireElapseTime = 0; } else { } } } } 記錄子彈發射后的時間,然后在大于時間間隔后才能發射下一個子彈。
武器父類:
using UnityEngine; using System.Collections; using System; public class Weapon : MonoBehaviour { //子彈時間間隔
protected float m_fBulletInterval = 0; //子彈類型
public String m_typeName =""; public float GetBulletInterval() { return m_fBulletInterval; } // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public virtual void Fire() { } } 最基本的一種子彈:
using UnityEngine; using System.Collections; public class WeaponNormal : Weapon { private const int MAX_FP = 2; public Transform[] m_FirePoint = new Transform[MAX_FP]; public Rigidbody m_BulletPre; WeaponNormal() { m_fBulletInterval = 2; m_typeName = "Normal"; } // Use this for initialization void Start () { } // Update is called once per frame void Update () { } public override void Fire() { for(int i = 0; i < MAX_FP; i++) { Rigidbody clone = (Rigidbody)Instantiate(m_BulletPre, m_FirePoint[i].position, m_FirePoint[i].rotation); clone.velocity = transform.TransformDirection(Vector3.forward * 20); } } } m_FirePoint是一個數組,存儲了發射子彈的位置。在編輯器中,可以在飛機周圍用空的GameObject放置一系列炮口的位置,然后拖入這個數組中。MAX_FP定義了炮口的數量。這里邊用到了速度屬性,這個是rigidbody才有的,所以在設置子彈的prefab時一定要為它加上rigidbody才行。 結構如下圖所示:
最后的效果圖:
現在子彈出來了,但是我們沒有加上子彈的消亡,這樣子彈被創建出來后就一直存在于場景中不會消失,會越積越多,所以我們讓子彈在移出屏幕時就把他銷毀掉。
using UnityEngine; using System.Collections; public class BulletControl : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () {
Vector3 screenPos = Camera.mainCamera.WorldToScreenPoint(this.transform.position); //print(screenPos.y); if (Screen.height < screenPos.y) Destroy(transform.gameObject); } } 將這個腳本掛接在子彈的prefab上就可以實現效果了。
己方的飛機控制已經初步完成了,現在要加入敵機了。
理論上應該有兩種方式:
1.預先設定,就是在編輯器里在你想要的位置上加上敵方的攻擊單位
2.動態生成,根據游戲進行的時間來控制敵方攻擊單位的產生。
這邊采用第2個方式來產生,有一些地面單位倒是可以用第一種方式來產生。
我們首先要設置一個敵機的產生位置,用空的object可以隨意的定一個坐標。
using UnityEngine; using System.Collections; public class EnemyManager : MonoBehaviour { public GameObject m_EnemyPre; public Transform m_CreatePoint; //一波飛機的數量
public const int MAX_GROUP_ENEMYS = 4; //兩波飛機之間的時間間隔
public float GROUP_INTERVAL = 2.0f; //同一波中兩架飛機之間產生的間隔
public float CREATE_INTERVAL = 0.25f; private float m_fTimeAfterOneGroup = 0.0f; private float m_fTimeAfterCreate = 0.0f; private int m_nEnemyNum = 0; // Use this for initialization void Start ()
{ } // Update is called once per frame void Update ()
{ m_fTimeAfterOneGroup +=Time.deltaTime; m_fTimeAfterCreate += Time.deltaTime; if (m_fTimeAfterOneGroup > 2.0f) { if (m_fTimeAfterCreate > 0.25f) { GameObject clone = (GameObject)Instantiate(m_EnemyPre, m_CreatePoint.position, m_CreatePoint.rotation); clone.AddComponent("MoveScript_Shake"); m_nEnemyNum +=1; m_fTimeAfterCreate = 0; } if (m_nEnemyNum == MAX_GROUP_ENEMYS) { m_fTimeAfterOneGroup = 0.0f; m_nEnemyNum = 0; } } } } 敵機的移動腳本,可自己再定義新的移動腳本,在創建新敵機時掛上去就好:
using UnityEngine; using System.Collections; public class MoveScript_Shake : MonoBehaviour { //標志左右移動方向
private int m_nDir = 1; //原始位置
private Vector3 m_OriginalPos; //水平移動速度
public float m_HoriSpeed = 0.1f; //翻轉速度
public float m_RotSpeed = 1.0f; //向前移動速度
public float m_MoveSpeed = 0.0005f; public Vector3 curScreenPos; public Vector3 LDPoint; // Use this for initialization void Start ()
{ m_OriginalPos = transform.position; LDPoint = GameObject.Find("LDPoint").transform.position; print (LDPoint); } // Update is called once per frame void Update ()
{ float relativeOffset = transform.position.x10) { Destroy(this.gameObject); } // print("Cur:"+transform.position); // if (transform.position.z < LDPoint.z) // { // Destroy(this.gameObject); // } } } 實現效果:
原來那個用Unity3D自帶的火焰老改不出想要的效果,去看了一個教程,調出一個還好的感覺。
最后的效果是:
本文轉自:http:///gameprogram/
第四篇:Unity3d射擊游戲報告
Unity3D游戲開發
課程設計實驗報告
項目名稱 GoldCoinGame 班 級 11402 小組成員唐智 梁俊龍薛柯 高立存 姓 名唐智 學 號1404240717
1.游戲說明
游戲運行畫面:
游戲目標:收集八個硬幣,得到的硬幣數量會顯示在右上角。
游戲菜單:按esc顯示,有三個選項:繼續游戲,重新開始和退出游戲。
操作:WASD控制方向,12切換武器,r填裝彈藥,空格space跳躍。
步槍狀態下: 鼠標右鍵——瞄準
手槍狀態下: 鼠標右鍵——消音器
2.游戲素材來源:
1. 開火音效:手槍與步槍開火音效來源于課堂上的實驗:Fps游戲中的MachineGun開火音效。 裝彈音效:來源于網絡。
2. SkyBox,水,Terrain的草地和椰樹等來源于課堂上的實驗:Survivalland。
3. 工廠模型Hangar_Full:來源于網絡。
Cube的貼圖:來源于網絡。
4. 步槍和手槍模型及其動畫:來源于網絡。
5. 金幣模型,塑料凳模型:使用3dmax軟件自制。
6. 顯示金幣數量的CoinGUI的9張圖片:采用Windows畫圖軟件繪制。
3.Unity版本:
Unity 5.5.2f1 (64-bit)
4. 操作步驟
1.首先創建環境,CreatEmpty——Environment,將課堂上做過的水的預制體 DaylightWater放入到其下。
2.創建一個Terrain和三個DirectionalLight。
3.地形的凸起和凹陷操作界面
4地形的貼圖操作界面
5.設置樹木和草地。
7. 調整好光線角度,再把工廠預制體拖到小島上。效果預覽
8. 創建一個Empty,給它添加Capsule,MeshRenderer,CharacherController, 和Rigibody。(MouseLook和CharacterMotor以及Fpsinput均是課堂上使用過的例子,之后會用到)
9. 將Empty命名為MyFirstPersonController,將tag改為Player。把主攝像機移動到該目錄下。
10.在攝像機maincamera下添加如下的Empty:weapon——m4a
1、handgun,用來存放武器。此外,再給camera添加skybox,選取合適的天空盒。
11.weapon添加一個js文件playerweapon,將步槍和手槍的預制體分別加到m4a1和handgun下。
Playerweapon.js主要控制武器的基本操作:開火,換彈和切換武器。 function Update () {
if (Input.GetButton ("Fire1")) {
BroadcastMessage("fire");//對子類發送fire的信息,從而達到調用所有名為fire函數的效果 }
if (Input.GetButton ("reload")) {
BroadcastMessage("reload"); }
if (Input.GetKeyDown("1")) {
BroadcastMessage("draw");//按1時播放動畫 SelectWeapon(0); }
else if (Input.GetKeyDown("2")) { SelectWeapon(1); } } function SelectWeapon (index : int) {
for (var i=0;i
// Activate the selected weapon
if (i == index)
transform.GetChild(i).gameObject.SetActive(true);
// Deactivate all other weapons
else
transform.GetChild(i).gameObject.SetActive(false); }
}//切換武器的函數
12.給empty添加m4_preview,該文件主要負責步槍的子彈數量和開火音效播放,以及步槍的裝彈。之后添加audiosource,選擇開火的子彈發射音效文件。
13.添加一個UI----canvas,加入兩個text,用來顯示兩把武器的子彈數目。
M4_preview的主要函數: function Update () {
GameObject.Find("/Canvas/Text").GetComponent(Text).text=" :"+ bulletsLeft+"/∞";//該函數可以將步槍子彈數量傳遞給text }
function fire () {
if (bulletsLeft == 0)
return;
if (Time.timeTime.deltaTime;
// Keep firing until we used up the fire time
while( nextFireTime < Time.time && bulletsLeft != 0) { GetComponent.().Play();//每發射一枚子彈,就播放一次開火的音效
FireOneShot();
nextFireTime += fireRate; }
Update ();//實現開槍后刷新text的子彈數量 }
function FireOneShot () {
var direction = transform.TransformDirection(Vector3.forward);
var hit : RaycastHit;
if (Physics.Raycast (transform.position, direction, hit, range)) {
// Apply a force to the rigidbody we hit
if (hit.rigidbody)
hit.rigidbody.AddForceAtPosition(force * direction, hit.point);
if (hitParticles) {
hitParticles.transform.position = hit.point; hitParticles.transform.rotation =
Quaternion.FromToRotation(Vector3.up, hit.normal); hitParticles.Emit(); }
// Send a damage message to the hit object
hit.collider.SendMessageUpwards("ApplyDamage", damage,
SendMessageOptions.DontRequireReceiver); }
bulletsLeft--;
m_LastFrameShot = Time.frameCount; enabled = true;
// Reload gun in reload Time
if (bulletsLeft == 0)
BroadcastMessage("reload");//沒有子彈后自動裝彈
}
function reload () {
yield new WaitForSeconds(1);//裝彈等待時間
if (clips > 0) { //彈夾數量大于0時才可裝彈
clips--;
bulletsLeft = bulletsPerClip;
}
Update ();//裝彈完成后更新text顯示的子彈數量
yield new WaitForSeconds(1); }
14.步槍的預制體m4animation,m4.js主要負責步槍的開火、裝彈等動畫播放。 給它添加一個audiosource,選擇下載的武器換彈音效。
15.手槍的步驟和步槍類似,就不在闡述,不同處如需要修改開火的速率(firerate)等參數即可。
16.添加兩個武器的貼圖到顯示彈藥的text的左側,再添加一張背景圖,調整好位置后效果如圖:
17.添加菜單:在canvas中添加一個panel,在panel下添加三個button,分別對應退出,重新開始和繼續,再添加一個text,內容為 “已暫停”。
18.添加一個empty命名為_GM,給他添加Manager.cs,一個負責菜單的文件。
其主要部分如下:
void Start () {
UIPanel.gameObject.SetActive(false); isPaused = false; }
void Update () {
if(Input.GetKeyDown(KeyCode.Escape) && !isPaused) Pause();
else if(Input.GetKeyDown(KeyCode.Escape) && isPaused) UnPause(); }
public void Pause() {
isPaused = true;
UIPanel.gameObject.SetActive(true);
Time.timeScale = 0f; }
public void UnPause() {
isPaused = false;
UIPanel.gameObject.SetActive(false);
Time.timeScale = 1f; }
public void QuitGame() {
Application.Quit(); }
public void Restart() {
Application.LoadLevel(0);
}
主要負責對應菜單的按鈕的功能
之后,給三個按鈕加上相應的貼圖和文字,在OnClick一欄中,選擇_GM,
在右側下拉選擇之前manager中對應的函數,比如退出游戲的Quit按鈕就選擇QuitGame。 另外,編輯Panel的image,可以更改菜單的背景圖片。
效果如圖
19.建立cube的預制體:創建一個3dobject,建立一個cube,再放在預制體的文件夾perfabs里,再更改cube的貼圖為黑色,命名為cube_dead,同樣拖入perfabs中。
給預制體cube添加一個DamageReciver,使它能接收到子彈的傷害,從而從cube轉換成cube_dead。
同時,勾選中iskinematic,讓這個預制體被子彈擊中前不受到里的影響,這樣可以把cube懸空而不掉落,而變成cube_dead則會掉落。
20.把制作的coin模型導入,添加剛體,同樣勾選iskinematic,并加入CapsuleCollider,勾選isTrigger,最后關聯Coin.cs。
void Update () {
transform.Rotate (new Vector3 (rotationSpeed * Time.deltaTime, 0, 0)); }
void OnTriggerEnter(Collider col) {
if (col.gameObject.tag == "Player") {
col.gameObject.SendMessage ("itemPickup"); Destroy(gameObject); } }
分析:
硬幣沒被拾取時,會沿著x軸旋轉
玩家觸碰到coin時,會傳遞一個信息itemPickup,提示該硬幣已經被拾取,之后會銷毀該硬幣。
21.回到第一人稱控制器,給MyFirstPersocontroller添加腳本item, 選擇金幣拾取音效、拾取貼圖。創建并添加提示文字GUItext。
創建一個empty命名為CoinGUI,添加guitexture,選擇image為coin0,即沒有失去硬幣時候的顯示圖。Coin到Coin8依次對應獲得八個硬幣的顯示圖。
22.準星的添加:創建一個empty,添加crosshair腳本,將網上下載的準星貼圖添加進來。
大致的步驟就如上所述。
小組成員:唐智
主要負責部分:武器模塊和esc菜單模塊以及實驗報告的編寫。
武器的部分是由我制作的,相對于我們課堂上制作的火箭筒和步槍,這個項目里面多了reload這個動作,并且是可以主動按r來reload的(課堂上的項目只能打空彈匣來換彈)。
開始時,我在原來的腳本基礎上修改代碼,想把調用動畫的代碼也寫進計算子彈fire和reload的代碼中,但是出現了很多問題:如動畫不能正常播放、或是播放了動畫不開火等。
最后,我將這兩個部分的腳本分開到兩個目標上,解決了這些問題。 第二個小問題,就是裝彈后子彈數量沒有實時更新到text里面,但是開火后子彈數量會重新刷新。這個問題通過在reload函數末添加了顯示子彈數的代碼后解決。
這次在原來的游戲基礎上新添加了esc菜單這一功能,腳本使用c++編寫。 在操作完后要注意的是需要完成File—buildsetting—add openscenes 這樣才算是完成,因為 Application.LoadLevel(0);這句代碼中的0就是代表著我們add的這個場景位于第一位,這樣restart按鈕才能進入到這個場景的初始階段,達到重新開始的目的。
第五篇:unity3d游戲開發之登錄注冊應用
在注冊的時候,輸入了數據庫已存在的用戶名,會顯示用戶已存在。
//驗證用戶是否存在
Users u = new Users().register(name);
if (name == u.Name)
{
name = "該用戶已存在";
a =GUI.Button(new Rect(600, 360, 40, 20), "注冊");
}
在登錄的時候,當用戶輸入錯誤密碼或用戶名就會出現提示:
章來自狗刨學習網
代碼部分:
如果用戶名和數據庫的不同
就提示:
print("用戶或密碼錯誤");
name = "";
password = "";
flag = true;
這篇文章來自狗刨學習網
這篇文