我們這篇要來講物件的產生,和彼此間的碰撞
前一篇講過的東西,這篇都會直接帶過
所以建議先看過前一篇再來看這篇
本篇分5個小節:
1. 飛彈製作
2. 消除子彈的牆壁
3 敵人的產生
4. 消滅敵人的牆壁
5. 敵人撞到子彈或飛機,同時消滅
1. 飛彈製作
首先,先用小畫家畫10 X 50像素的藍色長方型
作為飛機的雷射子彈
畫好後存成PNG檔
把它拖曳到ASSET裡,再拖曳到場景裡
成為一個叫Laser的物件
1. 加入Box Collider 2D和Rigidbody 2D
2. Rigidbody 2D底下,Gravity改成0,不受重力影響
3. Fixed Angle打勾,角度固定 (新版是Freeze Rotation Z打勾)
新版本的Fixed Angle換位置了
在Constraints底下的Freeze Rotation Z打勾
然後加入描述程式
在void Update()底下加入
gameObject.transform.position += new Vector3(0,0.1f,0);
這樣他就會在Y方向不斷增加0.1,也就是一直往Y方向移動
接著把Laser這個物件的名稱改成LaserObject
對著Laser按右鍵,選Rename
改成LaserObject,以便跟Laser的圖片做區分
接著把LaserObject拉到Asset裡,就會複製一個到Asset裡
然後刪除Hierarchy裡的LaserObject
因為我們是要按發射鍵時,才會產生這個雷射子彈
不需要他一開始就在場景裡
然後打開前一回寫的ShipControl
在開頭加上
public GameObject Bullet; 宣告一個物件叫Bullet
然後在void Update()底下加入
if (Input.GetKeyDown(KeyCode.Space))
{
Vector3 pos = gameObject.transform.position + new Vector3(0,0.6f,0);
Instantiate(Bullet,pos,gameObject.transform.rotation);
}
上一回有用過GetKey
GetKey和GetKeyDown的差別
GetKey是按著可連發
GetKeyDown是按下去一次只算一次
if (Input.GetKeyDown(KeyCode.Space)) 如果按下空白鍵,就會觸發大括號裡的描述
我們跳過一行,先講下面的Instantiate
Instantiate(Bullet,pos,gameObject.transform.rotation);
Instantiate就是產生物件的指令
他的格式是
Instantiate(物件, 初始位置,初始角度)
這邊物件就用我們剛剛設定的Bullet
初始位置設pos
初始角度就同飛機的角度
讓我們再回到前一行
Vector3 pos = gameObject.transform.position + new Vector3(0,0.6f,0);
這行是說,宣告一個位置pos
這個位置等於飛機的位置再加上0.6,也就是在飛機的前端
如果我們從飛機的中心位置產生子彈,子彈會馬上撞到飛機
讓子彈和飛機都彈開
然後我們按存檔
回到飛機的物件,我們會看到他的描述程式底下會出現一個Bullet的空格
後面寫None代表尚未指定
接著把LaserObject拖曳到Bullet的空格裡
存檔Ctrl+S後,按PLAY
測試子彈能不能發射
成功的話,會看到很多LaserObject(Clone)的物件
2. 消除子彈的牆壁
這邊會產生一個問題,射出去的子彈會一直往前飛,無法消除
最後累積太多子彈,然後當機
所以我們要在場景外面做一道牆
讓子彈撞到牆,然後消滅
GameObject -> Create Empty
開一個空的物件,改名為TopSide
1. 位置Y設5,X和Z設0
2. 加入Box Collider 2D
3. Is Trigger打勾,撞到東西時會觸發事件
4. Size X=6, Y=0.5
5. 加入程式描述
增加Trigger事件的Function
注意!這段程式碼不是放在void Update()的大括號{}裡面
是放在void Update()的大括號{}的後面(詳見圖片)
放錯位置程式碼可能會無效,子彈就不會消失
void OnTriggerEnter2D(Collider2D col)
{
if (col.tag == "Bullet")
{
Destroy(col.gameObject);
}
}
void OnTriggerEnter2D(Collider2D col)
觸發開始時,執行大括號內的動作,觸發事件的名稱是col
if (col.tag == "Bullet")
如果引起觸發的物件的標籤是Bullet,就執行大括號內的動作
Destroy(col.gameObject);
消滅引起觸發的物件
接著,把LaserObject的標籤設成Bullet
按Add Tag新增標籤
按"+"新增,輸入Bullet
選項裡就會有Bullet可選了
存檔Ctrl+S後,按PLAY
測試子彈撞到牆壁會不會消失
本篇要講的功能就是這兩個,物件的產生和碰撞觸發
之後都是做一樣的動作,讓我們重複練習一下
3 敵人的產生
用小畫家畫一個外星人
拖曳到Asset,再放到場景裡
加入設定
1. 標籤 Emeny (經網友提醒,正確拼法是Enemy。我從頭到尾都拚錯,所以程式還是能執行)
2. 加Box Collider 2D,然後Is Trigger打勾
3. 加Rigidbody 2D,Gravity設0
4. Fixed Angle固定角度打勾 (新版是Freeze Rotation Z打勾)
新版本的Fixed Angle換位置了
在Constraints底下的Freeze Rotation Z打勾
加入描述程式
在void Update()底下加入
gameObject.transform.position += new Vector3(0,-0.01f,0);
Y方向-0.01,緩慢得往下移動
然後改名成InvaderObject,拉到Asset裡
然後刪除Hierarchy裡的InvaderObject
在Background背景物件裡加入程式描述
開頭
public GameObject Emeny; //宣告物件,名稱Emeny
public float time; //宣告浮點數,名稱time
然後在void Update()底下加入
time += Time.deltaTime; //時間增加
if(time>0.5f) //如果時間大於0.5(秒)
{
Vector3 pos = new Vector3(Random.Range(-2.5f,2.5f),4.5f,0); //宣告位置pos,Random.Range(-2.5f,2.5f)代表X是2.5到-2.5之間隨機
Instantiate(Emeny,pos,transform.rotation);//產生敵人
time = 0f; //時間歸零
}
然後把InvaderObject,拉到Emeny的空格
存檔Ctrl+S後,按PLAY
然後我們就會看到很多外星人了
4. 消滅敵人的牆壁
無限的外星人也是會當機的
所以我們在畫面下方加一道牆來消滅這些外星人
加入空物件GameObject → Create Empty
改名為Bottom Side
1. position Y設-5,X和Z設0
2. 加入Box Collider 2D
3. Is Trigger打勾
4. Size X=6, Y=0.5
5. 加入程式描述
跟上方的牆的描述一樣,只差在tag標籤是Emeny
注意!這段程式碼不是放在void Update()的大括號{}裡面
是放在void Update()的大括號{}的後面(詳見圖片)
void OnTriggerEnter2D(Collider2D col) //碰撞事件
{
if (col.tag == "Emeny") //如果標籤是Emeny
{
Destroy(col.gameObject); //消滅碰撞的物件
}
}
5. 敵人撞到子彈或飛機,同時消滅
在InvaderObject的程式描述裡
加入觸發事件
void OnTriggerEnter2D(Collider2D col) //名為col的觸發事件
{
if (col.tag == "Ship" || col.tag == "Bullet" ) //如果碰撞的標籤是Ship或Bullet
{
Destroy(col.gameObject); //消滅碰撞的物件
Destroy(gameObject); //消滅物件本身
}
}
最後設定飛機的標籤Ship,就大功告成囉
到此,遊戲的基本功能都有了,只是有點單調
下一篇,會講動畫和音效,讓你的遊戲活起來!
前往下一篇
想要了解程式的觀念,請參考 初學者如何建立程式的觀念(Scratch教學)
參考文件:
勇者拉德小酒館 Unity-射擊遊戲系列(1/?) 玩家子彈射擊
http://jerrard-liu.blogspot.tw/2014/11/ShootingGame1.html

謝謝~版主的用心!! 把Unity講解得較為簡單易懂
謝謝,希望大家都能輕鬆學會Unity ^^
你好,請問為什麼SAVE專案後再開啟,背景會覆蓋掉spaceship的spirte,使不能看見spaceship,我應該如何讓spaceship在背景之上出現?謝謝!
請參考上一篇sorting layer的部分,你可以移動layer來決定物件的前後 已修改上一篇的內文,那邊我沒有解釋到,感謝你的反映! ^_^
請問 如果是碰到飛機 就讓遊戲結束 ,並秀出end的圖片~~要怎麼做呢~~
這個部分會在part4作說明 ^_^
感謝版主!完全沒接觸過unity 第一次就直接跟著你的文章做 已慢慢了解了!期待part3
很高興對你有幫助 ^_^
謝謝版主, 看那麼多教學還是覺得版主的最容易上手, 跟著做就可以慢慢了解怎麼使用Unity :D 但是不知道為什麼 我在設定敵人出現的部分 把X及Y的位置調換之後 試玩時都會顯示要調整那一行 Vector3 pos = new Vector3(Random.Range(-2.5f,2.5f),4.5f,0); 改成 Vector3 pos = new Vector3(Random.Range 4.5f,(-2.5f,2.5f),0); 或是 Vector3 pos = new Vector3(Random.Range (-2.5f,2.5f),(-2.5f,2.5f),0); P.S. 我做的是橫式的 再次感謝!!
恩,是new Vector3( 4.5f, Random.Range(-2.5f,2.5f), 0); 這邊我沒有講得很清楚,感謝你的回應,已修改內文
大大不好意思, 剛剛又研究一次終於知道為什麼了!!
讚! :D
請問一下 我背景下增加的程式碼一直無法顯示Emeny和Time的空格 取額代之下面是黃色的驚嘆號 請問我大概是哪一邊做錯了?
哦哦哦@@ 我剛刪掉重做問題已解決
讚! ^_^
你好~~ 我有問題~~ 我的子彈只出現一發後 遊戲也不動了~~ 我很認真地仔細看過~~ 另外我也是5.1版 但是沒有看到Fixed Angle這個選項
Fixed Angle換位置了,改在constraints裡的Freeze Rotation Z 遊戲不動的話,看一下console頁面的錯誤訊息,會有說明
嗨你好~我是看著你的發文學做UNITY的~ 老實講這是我看過最容易讓初學者上手的文章了~ 不過我有個小問題~ 為什麼我的敵人跟主角感覺像在不同層一樣~ 就算碰到也不會銷毀~這個什麼原因呢?
謝謝 ^_^ 1. 外星人的Is trigger沒打勾 2. Save後執行試試 3. 如果還是不行的話,重開Unity
嗨~你好~關於你的說法,我昨天測試過了~ 沒有用~ 而且不知道為什麼現在子彈也設不出來了~
你好~~我知道為什麼我子彈射不出來了!! 因為空白建的發射 也變成GAME視窗的播放暫停(正好是同一個快捷鍵) 所以 if (Input.GetKeyDown(KeyCode.Space)) 是不是這語法裡的Space 可以更改為ALT
你好~~~我更改語法後(不管那個按鈕) 只要發射子彈 他的播放就會直接幫我暫停..... UnassignedReferenceException: The variable Bullet of Shipcontrol has not been assigned. You probably need to assign the Bullet variable of the Shipcontrol script in the inspector.
你沒有指定Bullet是哪個物件 請參考文章中「把LaserObject拖曳到Bullet的空格裡」那段
喔喔~~感謝你!!! 原來我放了兩個子彈程式碼...現在變成雙發了XDD 部過遊戲進行順利!! 希望還有之後教學~~ UI放置~~
雙發,讚喔 XD 教學Part4近期會出 ^_^
你好~~~ 想請問 卡在 飛機物件 有一個描述程式的問題 我案存檔後 他並沒有跑出描述物件 BULLET 請問我要怎麼自己讓她產生出來?
不好意思 在請問一下 現在卡在子彈的部分!!!! 很苦惱阿...只要一輸入指令 就是錯誤!! 明明已經把子彈加入 Bullet這個描述程式理面了
是什麼樣的錯誤訊息呢?
不好意思問一下 我射出子彈後飛機會一直往後退是不是跟子彈碰撞到飛機有關? 有什麼可以解決的方法嗎??
是的,子彈和飛機間要留一個距離 不然會撞到,文章中有提到喔 如果距離0.6太短,請自行增加到不會撞到為止
不好意思問一下 我成功製造出子彈,但是都在背景下方無法顯示 請問是要把它加入layers或是sorting layers嗎?
是的
我Bullet的空格沒出來
而且還出現: 20 程序無法存取檔案,因為檔案正由另一個程序使用
when the ship shoots it goes down
Left a gap between ship and bullet to avoid they collide when shooting
版主你好: 請問如果我要再另外一台電腦執行這個project可以把這個project直接複製到另外一台電腦然後執行嗎,因為當我用另一台電腦開啟這個project後它顯示我的C#檔案is missing,請問這個問題要如何解決呢><
可以阿,整個Project的資料夾都COPY過去即可
版主您好 首先很感謝您的教學,讓我這個初學者很快上手 但是想請教一下關於這行程式碼"void OnTriggerEnter2D(Collider2D col)" 我輸入之後在"Collider2D col"的部分會出現紅色底線的錯誤 請問是那邊沒設定好呢? 謝謝
*****
*****
你好 請問一下 我現在遇到一個問題 子彈有時會射不出來 程式都沒顯示錯誤 也有存檔 可是就是會出現說 一開始可以發射 但關掉後再開啟 他就射不出來了 重寫後可以運作 可是一段時間後就又射不出來了 其他功能則一切正常 請問該如何解決呢
會不會你的電腦中病毒了?
板主您好,首先感謝您的教學說明讓我受益良多 我想請問,有關隨機生成大量物件那邊的問題 假設我想要讓隨機生成出來的外星人 彼此之間有碰撞(不會重疊) 請問要如何做呢,謝謝您!!
讓他們隔遠一點就不會撞到囉 還是你想要讓他們擠成一團又不重疊? 那就要取消IsTrigger,但這樣碰撞相關的程式就不會觸發 就要改成其他方式來觸發了
請問一下我的雷射剛寫完程式都能射出但是重開後就無法 為什麼呢?
可能是雷射的程式有問題喔
版主你好 我的子彈不會依直往前飛ㄟ 她停在我飛機前面一動也不動 這個該如何解決呢?
島主您好 我是個初學Unity的小渣渣 看了您的文覺得受益頗多 照做之後大概99%都沒問題 唯獨就是遊戲一開始馬上就會有一台外星人自爆 完全不知道怎麼回事 程式碼方面完全沒錯 請問我該從何下手? 謝謝指教
很高興對你有幫助 ^_^ 可能是有一個雷射留在場上喔
大大我的飛機會跟飛彈一起往前飛也就是按射擊時,飛機也會往前0.6
版主您好 我是個unity的初學者 在void Ontriggerenter2D (Collider2D col) { if (col.tag =="bullet") { Destroy(col.gameObject); } } 這部分,不管怎麼打都無法成功 可以幫幫我嗎?
Ontriggerenter2D的T跟E要大寫 →OnTriggerEnter2D
請問,子彈都照著ˊ設定走,標籤也有設定好,可是就是會繼續穿過牆壁, 重點是...飛機標籤改成Bullet之後,他撞到牆壁反而會消失耶... 請問這是哪裡的問題呢QQ?
子彈有加Rigid body嗎?
你好, 我想請教一下 "回到飛機的物件,我們會看到他的描述程式底下會出現一個Bullet的空格" 這步驟, 指令完成後,Bullet的空格沒有出來, 請問可能是有什麼問題?
程式要存檔才會出現空格喔
*****
為甚麼發射子彈後飛機會往後退?
產生子彈的時候,如果跟飛機靠太近,就會撞到飛機,飛機就會往後移
為甚麼我的子彈會撞到攝影機.....
發射子彈,不知道為什麼按空白鍵要這麼做,而其他鍵卻不用 我的狀況是: 用下面這行會失敗 if (Input.GetKeyDown(KeyCode.Space)) 要改成這樣 if ((bool) Input.GetKeyDown(KeyCode.Space))
誰和我一樣有這個問題? 按[Shift鍵]能開關 是否能偵測到按了[空白鍵] 這個功能 若關閉的話 if(Input.GetKeyDown(KeyCode.Space)) //可拿掉(bool) { //此處就算按了[空白鍵]也不會觸發 }
樓上幾個的問題都可以重複檢查,文章是否有打錯,像是子彈往下飛可能是設定gameObject.transform.position += new Vector3(0,0.1f,0); 的時候,可能有地方設錯。 我的問題是:子彈往上碰到TopSide的時候可以被Destroy,但是外星人往下掉的時候BottomSide就沒辦法被Destroy,Tag也改對了程式碼也沒有錯,請問可能是哪裡出現問題呢?可否給我指點一下,謝謝。
BottomSide的程式位置可能不對
問題解決。重新刪掉在重打就成功了。 建議大家有錯誤的地方除了再三檢查外,也可以刪除出錯的地方重做一次(素材、程式碼都要刪) 謝謝樓主的教學,真的很實用,現在正在研究我只要用GetKey就會變成很奇怪的閃彈槍呈現V字型的發射,但GetKeyDown卻是好的 QAQ
因為一次出來太多子彈,互相碰撞往左右彈開
我想要問一個問題是 我做完了之後 但是目前遇到了兩個問題 第一個是 我自己的本體物件 他撞到最下面的Bottom他會自己消失 第二個是我在每一次的發射子彈出去的時候 我主要的物件他會一直退 然後退到最下面 碰到Bottom的時候他就消失了 不知道是哪裡出了問題 大大可以稍微點一下 或者是大概抓一下有可能是哪裡錯了而導致 謝謝~~~
產生子彈的時候,如果跟飛機靠太近,就會撞到飛機,飛機就會往後移
請問為何子彈跟敵人都在背景層下面出不來?... Layer那邊要怎麼設定才會出來@@"
調整sorting layer試試看
請問我的城市都照著打可是為甚麼子彈出不來 所有都依樣可是案了子彈就是出不來
不好意思,我有個小問題~ 為什麼我的敵人跟主角感覺像在不同層一樣,就算碰到也不會銷毀,這個什麼原因呢? 外星人的Is trigger也有打勾了,也Save後執行試試也不能,重開Unity也不能,換一台電腦也不能,程式碼都一樣但是主角卻死不了,為什麼?
可能是外星人的程式碼有問題吧
感謝作者的辛勞 我遇到一個問題是,我把飛機設定成可以四個方向移動,所以設定了四個邊界,但是當我將上方邊界設置Trigger之後,飛機與laser都可以穿過上方邊界,這是哪裡出了問題呢?
應該是上方邊界的程式有問題吧,我猜
我一直按著上面的做 , 但到Background 產生敵人的那個位置 C# 裡的看了很多遍也沒有錯 但Background 上面的GameFunction (Script) 只有一個Script 沒有empty 而且顯示The associated script can not be loaded. Please fix any compile errors and assign a valid script. 為什麼...
程式有錯喔
另外外星人裡 加入設定 1. 標籤 Emeny 2. 加Box Collider 2D,然後Is Trigger打勾 3. Gravity設0 4. Fixed Angle固定角度打勾 那個Emeny 是自己在TAG ADD嗎 可是之前什麼關於這個Emeny都沒有的吧
對,之後程式裡會有
我在這邊寫一下飛機會往後飛的解決方法,因為我飛機圖案是自己找的圖,所以圖片大小和碰撞判斷範圍和作者大大不同,因為飛機和子彈都有設定碰撞屬性,因此假如你子彈一出來就和飛機的碰撞範圍相觸的話,兩個會彈開,造成飛機往後退的案例發生。 解決方法很簡單,就把子彈出來的位置往前調一點就好了 另外感謝作者大大的文章,讓我獲益良多
很高興對你有幫助 ^_^
大大為甚麼OnTriggerEnter2D一直出現紅色波浪線請問該怎麼解決呢?
不知道 還有沒有辦法幫我解答.. 我已經到了part 4 了 但是我唯一的問題就是我的怪物 不會被我下面的牆給消滅 而且還會穿過去 ><"
應該是下面的牆的程式位置不對喔
我做的敵人和敵人碰在一起也會消失 可能是有哪部分打錯嗎?
檢查外星人的標籤,或是外星人程式裡col.tag是否正確
(我做的敵人和敵人碰在一起也會消失 可能是有哪部分打錯嗎?) 我找到問題了~~
Tag問題,我猜
版主教得太好了! 感謝!
很高興對你有幫助 ^_^
請問 我照你的步驟做 子彈射擊 案空白建 有射擊出來 但是看不到 子彈的圖示 是怎麼了
可能是在背景後面,試著調整Sorting layer
給#55 樓 要改子彈圖層 LaserObject 的Sprite Renderer -> Sorting Layer -> BulletLayer
To #51, 你子彈撞牆消失和撞牆消失寫在同一個檔, 應該就沒問題
To #51, #57 文中程式筆誤所致 將" Emeny" 改為 "Enemy" 就沒問題
補充 #58, 文中全部用"Emeny" 雖為錯字,注意程式中皆一致即可
我拼錯字了!真不好意思
版主不好意思 我的怪物會出生超級多然後都黏在一起 一直無線生怪 導致LAG請問是什麼原因阿
可以試著把生怪時間調長一點
TO #60 在同一位置生怪嗎? 你生怪時間設慢一點 生怪設上限
OnTriggerEnter2D 區域函式OnTriggerEnter2D已宣告,但從未使用 怎樣解決...
應該是程式放錯位置了
問問偵測死亡,要如何寫, void OnTriggerEnter2D(Collider2D col){ if(die != true) { if (col.tag == "diezone"){ die = true; 之後弄很多次都不行,請求幫忙
感恩版主,讓我可以複習unity
很高興對你有幫助 ^_^
為甚麼我的子彈碰到怪都直接穿過去??
#34 我也遇到 但是後來檢查是因為 public GameObject Bullet; 要放在 public shipcontrol 裡面!
OnTriggerEnter2D 區域函式OnTriggerEnter2D已宣告,但從未使用 怎樣解決... 快瘋了
可能是程式碼放錯位置囉
版主您好我的觸發事件都有問題像子彈穿過敵人、也不會被牆壁銷毀、敵人也不會被底下的牆壁銷毀,我的程式碼跟設定都一樣也檢查過很多遍了,還是有問題,後來我寫了一個偵錯的程式碼發現系統根本沒有跑到觸發事件那邊,請問一下這是什麼原因
可能是碰撞的程式碼放在void Update()的大括號{}裡面造成的錯誤
可是我確定我的程式碼是放在void Update( )的大括弧外面
碰撞就三個東西:IsTrigger打勾、設定RigidBody、程式 再檢查這三個地方看看
這是我之前完成的範例: https://youtu.be/L5zLhlCZbiI
不錯耶! 真有創意
謝謝版主,我發現我的tag是小寫不過程式碼是大寫,改好了就沒問題了,真的非常謝謝,期待下次還能有類似這種小遊戲的教學
謝謝版主,我發現我的tag是小寫不過程式碼是大寫,改好了就沒問題了,真的非常謝謝,期待下次還能有類似這種小遊戲的教學
恭喜你! ^_^ 有空的話會寫
產生敵人那邊我試了很久把放Random.Range執行不了 在unity網站看到有人說改成UnityEngine.Random.Range 然後就可以了 不知道是不是因為版本的關係
恩,有可能。我還沒下載最新版,所以我也不確定
不好意思,電腦課作業要用unity製作電流急急棒,請問要讓球被滑鼠點到後,即跟著滑鼠座標移動的程式要怎麼寫?
所以如果我想要按著連發的話就不用加Down了吧
是,但是連射太快,子彈會撞在一起變成散射
請問為何子彈飛不出去 卡在飛機前面而已
也許檢查一下子彈的程式碼,特別是移動那邊
版主 我有遇到跟76樓一樣的問題 也確認過程式碼+存檔+重開了 子彈也還是飛不出去