一、前言
? ? ? ?本案例是初級案例,意在引導(dǎo)想使用unity的初級開發(fā)者能較快的入門,體驗unity開發(fā)的方便性和簡易性能。
? ? ? 本次我們將使用團結(jié)引擎進行開發(fā),幫助想體驗團結(jié)引擎的入門開發(fā)者進行較快的環(huán)境熟悉。
? ? ?本游戲是一個俯視角度的射擊游戲。主角始終位于屏幕中心位置,玩家使用鍵盤控制主角移動,并可開槍射擊場景中的敵人。玩家具有多種武器,如手槍、霰彈槍和自動步槍,玩家可以切換武器。敵人也會向玩家方向移動并射擊玩家。當(dāng)玩家角色或敵人的生命值減為零時則死亡。當(dāng)玩家死亡后,游戲結(jié)束。
二、開發(fā)環(huán)境
????????操作系統(tǒng):Windows
????????Unity 版本:團結(jié)引擎1.0.0
????????團結(jié)引擎的安裝參考《團結(jié)引擎的安裝》
三、場景搭建
? ? ?3.1 創(chuàng)建項目
????????使用團結(jié)引擎新建項目和使用Unity Hub一樣。打開Tuanjie Hub,點擊左上角【create project】按鈕,選擇【3D】模版,輸入項目名稱和項目保存路徑,點擊右下【Create project】按鈕完成創(chuàng)建。
? ? ? ? ?3.2 搭建場景
? ? ? ? 1. 我們創(chuàng)建一個plane作為地面 。在Hierarchy面板上依次【右鍵】-> 【3D Object】->【plane】,將【Plane】創(chuàng)命名為【Ground】,并將x、z縮放大小變?yōu)?。我們將地面顏色改成灰色。新建文件夾,命名為【Materals】用來存放材質(zhì)。在材質(zhì)文件夾右鍵,依次選擇【Create】->【Material】, 并命名為【Ground】。修改材質(zhì)顏色為灰色(顏色值:4B4747),并將材質(zhì)拖拽到地面上。
? ? ? ? 2. 同樣,?我們創(chuàng)建一個膠囊體(Capsule)來作為主角,并命名為Player。創(chuàng)建一個立方體(Cube)放置在Player上,并調(diào)整到合適的位置。Cube將作為Player的正面,以便分辨方向。創(chuàng)建一個材質(zhì),命名為Face,改變材質(zhì)樣色為藍色(也可以設(shè)置成自己喜歡的顏色),然后把這個材質(zhì)賦值給Cube。
? ? ? ? 3.??調(diào)整攝像機角度
? ? ? ? 由于我們是俯視角度的射擊游戲,因此需要調(diào)整攝像機的位置。選中攝像機,將攝像機調(diào)整到Player后方合適的位置。
? ? ? ? 4. 創(chuàng)建敵人?
????????敵人角色與玩家角色造型基本一致,只是將白色換成紅色。我們復(fù)制場景中的Player(選中Player, 按 ctrl + D),命名為Enermy。然后創(chuàng)建一個材質(zhì)Enermy, 然后將材質(zhì)的顏色改為紅色。把材質(zhì)賦給場景中的Enermy物體。新建標(biāo)簽(Tag),命名為Enermy,將玩家Player的Tag設(shè)置為“Player”, Enermy 的Tag設(shè)置為“Enermy”,方便區(qū)分玩家和敵人。之后我們新建文件夾,命名為 Prefabs,將Enermy制作成預(yù)知體(直接把Hierarchy中的Enermy物體拖到Prefabs文件夾中)。
?四、編寫腳本,實現(xiàn)功能
? ? ? ? 上面基本場景已經(jīng)搭建完畢,接下來我們就開始編寫腳本,實現(xiàn)我們的游戲功能。
? ? ? ? 4.1 讓玩家動起來
? ? ? ? 首先,我們來編寫玩家腳本,讓玩家動起來。新建文件夾,命名為【Scripts】,用來保存我自己編寫的腳本文件。在【Scripts】右鍵->【Create】->【C# Script】,命名為Player。然后將Player腳本掛載到Player物體上。
? ? ? ? ?和《3D小球跑酷》類似,我們使用鍵盤來控制Player的移動。雙擊打開Player腳本,輸入以下內(nèi)容:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float speed = 10f; // 玩家的移動速度
public int maxHp = 10; // 玩家的最大血量
private int hp; // 玩家的當(dāng)前血量
private bool idDead = false;
void Start()
{
hp = maxHp; // 初始血量為最大值
}
void Update()
{
if (!idDead)
{
Move();
}
}
void Move()
{
var input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical")); // 接受鍵盤輸入
input = input.normalized;
Vector3 currentPos = transform.position;
currentPos += input * speed * Time.deltaTime;
if (input.magnitude > 0.1f)
{
transform.forward = input; // 使玩家面向移動方向
}
// 限制玩家的移動范圍,范圍為方圓20以內(nèi)
const float distance = 20f;
if (currentPos.x > distance)
currentPos.x = distance;
if (currentPos.x < -distance)
currentPos.x = -distance;
if(currentPos.z > distance)
currentPos.z = distance;
if(currentPos.z < -distance)
currentPos.z = -distance;
transform.position = currentPos;
}
}
? ? ? ? 保存腳本,運行游戲,按鍵盤上的方向鍵或者A、D、S、W鍵,可以看到Player朝著指定的方向移動起來了。
注意:
????????以上移動方式?jīng)]有考慮阻擋,為放置玩家或者敵人移動到地面的邊緣掉下去,我們使用了簡單的方式來限定他們的可移動范圍。
? ? ? 4.2 相機跟隨
? ? ? ? 運行游戲,發(fā)現(xiàn)Player在移動時,相機是固定的。下面我們把相機改為隨著Player移動而移動。在《3D小球跑酷》我們采用的是把相機直接作為Player的子物體的方式,這里我們采用另一中方式(當(dāng)然,你也可以使用作為子物體的方式),就是編寫相機跟隨腳本。
? ? ? ? 在Scripts文件夾下新建C#腳本,命名為FlowCamera。將腳本掛在到Camera上,雙擊打開腳本,輸入以下代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlowCamera : MonoBehaviour
{
public Transform target;
Vector3 offset;
void Start()
{
offset = transform.position - target.position;
}
void Update()
{
transform.position = target.position + offset ;
}
}
? ? ? ? 將Player物體拖拽到腳本參數(shù)target字段。保存再次運行游戲,發(fā)現(xiàn)相機已經(jīng)可以跟隨Player移動了。
? ? ? 4.3 制作子彈
? ? ? ? 創(chuàng)建一個球體,大小縮放為0.2倍。命名為Bullet, 這將作為我們發(fā)射的子彈。新建腳本Bullet,將腳本掛在到Bullet物體上。雙擊打開腳本,輸入以下內(nèi)容:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float lifeTime = 2f; // 子彈的生命周期
public float speed = 10f; // 子彈的飛行速度
float startTime; // 子彈的生成時間
// Start is called before the first frame update
void Start()
{
startTime = Time.time;
}
// Update is called once per frame
void Update()
{
transform.position += speed * transform.forward * Time.deltaTime;
// 超過一定時間后
if (startTime + lifeTime < Time.time)
{
Destroy(gameObject); // 銷毀子彈
}
}
}
????????將球體拖到Prefabs文件夾,做成預(yù)制體。
? ? ? 4.4?實現(xiàn)武器系統(tǒng)
? ? ? ? 下面我們實現(xiàn)一下Player切換武器的功能,這是我們游戲的一個重要功能。我們按Q鍵可以切換武器。武器有三種,分別是手槍(Pistol),自動步槍(Rifle)和散彈槍(shotgun)。
? ? ? ? 新建腳本,命名為Weapon。雙擊打開腳本,輸入以下內(nèi)容:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Weapon : MonoBehaviour
{
public GameObject bulletPrefab; // 子彈預(yù)制體
public float pistolFireCD = 0.2f; // 手槍發(fā)射子彈的時間間隔
public float rifleFireCD = 0.1f; // 自動步槍發(fā)射子彈的時間間隔
public float shotgunFireCD = 0.5f; // 散彈槍發(fā)射子彈的時間間隔
float lastFireTime; // 上次開火時間
public int curGun; //當(dāng)前使用的武器 0:手槍 1:自動步槍 2:散彈槍
// 開火方法,由角色腳本調(diào)用, keyDown 表示按一下就發(fā)射一顆子彈, keyPressed 表示長按
public void Fire(bool keyDown, bool keyPressed)
{
switch (curGun)
{
case 0:
if (keyDown)
{
PistolFire();
}
break;
case 1:
if (keyDown)
{
ShotgunFire();
}
break;
case 2:
if (keyPressed)
{
RifleFire();
}
break;
default:
break;
}
}
// 更換武器
public int ChangWeapon()
{
curGun += 1;
if (curGun >= 3)
curGun = 0;
return curGun;
}
// 手槍射擊
private void PistolFire()
{
// 子彈發(fā)射時間間隔判定
if (lastFireTime + pistolFireCD > Time.time)
{
return;
}
lastFireTime = Time.time;
GameObject bullet = GameObject.Instantiate(bulletPrefab);
bullet.transform.position = transform.position + transform.forward * 1.0f; // 子彈的位置,位于角色前方1米
bullet.transform.forward = transform.forward; // 子彈的方向
}
// 自動步槍射擊
private void RifleFire()
{
// 子彈發(fā)射時間間隔判定
if (lastFireTime + rifleFireCD > Time.time)
{
return;
}
lastFireTime = Time.time;
GameObject bullet = GameObject.Instantiate(bulletPrefab);
bullet.transform.position = transform.position + transform.forward * 1.0f; // 子彈的位置,位于角色前方1米
bullet.transform.forward = transform.forward; // 子彈的方向
}
// 散彈槍射擊,一次發(fā)射5顆子彈,子彈間隔10
private void ShotgunFire()
{
// 子彈發(fā)射時間間隔判定
if (lastFireTime + shotgunFireCD > Time.time)
{
return;
}
lastFireTime = Time.time;
for (int i = -2; i <= 2; i++)
{
GameObject bullet = GameObject.Instantiate(bulletPrefab);
var dir = Quaternion.Euler(0, i * 10, 0) * transform.forward;
bullet.transform.position = transform.position + dir * 1.0f; // 子彈的位置,位于角色前方1米
bullet.transform.forward = dir; // 子彈的方向
}
}
}
? ? ? ? 修改Player腳本調(diào)用武器系統(tǒng),使角色發(fā)射子彈。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
......
// 聲明武器對象
private Weapon weapon;
void Start()
{
hp = maxHp; // 初始血量為最大值
weapon = GetComponent<Weapon>(); // 獲取武器對象
}
void Update()
{
if (!idDead)
{
Move();
Fire(); // 開火,發(fā)射子彈
ChangeWeapon(); // 切換武器
}
}
void Move()
{
......
}
void Fire()
{
bool keyDown = Input.GetKeyDown(KeyCode.J);
bool keyPressed = Input.GetKey(KeyCode.J);
weapon.Fire(keyDown, keyPressed);
}
void ChangeWeapon()
{
bool changWeapon = Input.GetKeyDown(KeyCode.Q);
if (changWeapon)
weapon.ChangWeapon();
}
}
? ? ? ? 將武器腳本(Weapon)掛載到Player物體上,同時把子彈預(yù)制體拖到武器腳本的bulletPrefab字段上。保存場景,運行游戲,按Q鍵可以切換槍支,按J鍵可以發(fā)射子彈。讀者可以自行調(diào)整玩家的移動速度和子彈的發(fā)射速度,以獲得更好的游戲體驗。
? ? ? 4.5 實現(xiàn)敵人的腳本
? ? ? ? 敵人腳本和Player腳本類似,單敵人會始終朝著玩家前進,并朝著玩家發(fā)射子彈。在Scripts文件夾下新建腳本文件,命名為Enermy,并將其掛載到Enermy預(yù)制體上。雙擊打開腳本,輸入以下內(nèi)容:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enermy : MonoBehaviour
{
private Transform playerTransform; // player 的 transform 組件
public float speed = 2f; // 敵人的移動速度
public int maxHp = 1; // 敵人的最大血量
private int hp; // 敵人的當(dāng)前血量
private bool isDead = false;
private Weapon weapon;
void Start()
{
hp = maxHp; // 初始血量為最大值
weapon = GetComponent<Weapon>();
playerTransform = GameObject.Find("Player").transform;
}
void Update()
{
if (!isDead)
{
Move();
Fire();
}
}
void Move()
{
Vector3 dir = playerTransform.position - transform.position;
var currentPos = transform.position + dir.normalized * speed * Time.deltaTime;
// 限制敵人的移動范圍,范圍為方圓20以內(nèi)
const float distance = 20f;
if (currentPos.x > distance)
currentPos.x = distance;
if (currentPos.x < -distance)
currentPos.x = -distance;
if (currentPos.z > distance)
currentPos.z = distance;
if (currentPos.z < -distance)
currentPos.z = -distance;
transform.position = currentPos;
transform.forward = dir.normalized;
}
void Fire()
{
weapon.Fire(true, true);
}
}
? ? ? ? 然后,把武器腳本掛載到Enermy預(yù)制體上,保存。再場景中放置幾個敵人(直接把Enermy預(yù)制體拖到場景中即可),運行游戲,發(fā)現(xiàn)敵人開始朝著玩家移動,并不斷發(fā)射子彈。
? ? ? 4.6 子彈的碰撞邏輯
? ? ? ? 雖然現(xiàn)在我們可以控制Player移動,并且能發(fā)射子彈,敵人也能夠發(fā)射子彈,但是子彈碰到敵人或者Player都沒有反應(yīng),接下來我們就開始添加子彈碰撞的邏輯。
? ? ? ? 子彈和物體的碰撞分為以下幾種情況:
? ? ? ? 1)? Player的子彈擊中敵人
? ? ? ? 2)敵人的子彈擊中Player
? ? ? ? 3)玩家的子彈和Player的子彈碰撞
? ? ? ? 4)Player的子彈不會擊中Player,敵人的子彈也不會擊中敵人。
? ? ? ? 為了區(qū)分?jǐn)橙俗訌椇蚉layer的子彈,我們采用標(biāo)簽(Tag)來進行區(qū)分。我們新建兩個標(biāo)簽,分別為PlayerBullet和EnermyBullet。選中之前的子彈預(yù)制體,重命名為PlayerBullet, 并將Tag設(shè)置為PlayerBullet。復(fù)制PlayerBullet,重命名為EnermyBullet,并將Tag設(shè)置為EnermyBullet。
? ? ? ?4.6.1 修改Enermy預(yù)制體
???????雙擊Enermy預(yù)制體,將腳本W(wǎng)eapon上的BulletPrefab字段設(shè)置為EnermyBullet。保存退出。
??????4.6.2 修改Bullet腳本
? ? ? ?雙擊Bullet腳本,添加碰撞邏輯。添加以下代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
.....
private void OnTriggerEnter(Collider other)
{
if (CompareTag(other.tag)) // 如果子彈的tag和碰撞到的物體的Tag相同
return;
Destroy(gameObject);
}
}
? ? ? ? 4.6.3 修改Player腳本
? ? ? ? 當(dāng)敵人的子彈碰到玩家的時候,玩家血量減1,當(dāng)血量為0時,玩家死亡,游戲結(jié)束。雙擊打來Player腳本,添加以下代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
......
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("EnermyBullet"))
{
if (hp <= 0) return;
hp--;
if (hp <= 0)
{
idDead = true;
Debug.Log("Game Over!");
}
}
}
}
? ? ? ? 4.6.4 修改Enermy腳本
? ? ? ? 當(dāng)玩家的子彈碰到敵人的時候,敵人血量減1。當(dāng)敵人的血量為0時,敵人死亡。雙擊打開Enermy腳本,添加以下代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enermy : MonoBehaviour
{
......
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("PlayerBullet"))
{
if (hp <= 0) return;
hp--;
if (hp <= 0)
{
Destroy(gameObject);
}
}
}
}
? ? ? ? ? ?保存場景,運行游戲,發(fā)現(xiàn)子彈碰撞后并沒有什么效果,這是因為我們沒有添加剛體,并設(shè)置觸發(fā)器。
? ? ? ? 4.6.5 設(shè)置觸發(fā)器
? ? ? ? 選中敵人的子彈和Player的子彈的預(yù)制體,添加剛體組件(RigidBody),并勾選 Collider 上的Is Trigger 復(fù)選框。選擇Enermy預(yù)制體,并勾選 Collider 上的Is Trigger 復(fù)選框。選擇Player,并勾選 Collider 上的Is Trigger 復(fù)選框。保存場景再次運行游戲,發(fā)現(xiàn)Player 被擊中之后,血量減少,當(dāng)血量減少到0是,控制臺輸出“Game Over”。
? ? ? ? 4.7 生成大量敵人
? ? ? ? 現(xiàn)在我們的游戲已經(jīng)初具模型了,單要手動把敵人預(yù)制體拖到場景中,如果要有許多敵人就顯得太麻煩了,而且拖到場景中的敵人有限,殺完了就沒有了。?我們要有一個可以源源不斷生成敵人的機制,每隔一段時間就生成一個敵人,這樣就可以一直玩下去了。
? ? ? ? 在場景中新建一個空物體,命名為EnemySpawn,同時新建腳本文件,也命名為EnemySpawn,并掛載到EnemySpawn物體上。腳本內(nèi)容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnermySpawn : MonoBehaviour
{
public GameObject enermyPrefab;
public float spawTimer = 2.0f;
List<GameObject> enermies = new List<GameObject> ();
void Update()
{
if (enermies.Count >= 10) return; // 場景中最多10個敵人
spawTimer -= Time.deltaTime;
if (spawTimer <= 0)
{
spawTimer = 2.0f;
GameObject enermy = Instantiate(enermyPrefab);
enermy.transform.position = new Vector3(-20, 1, -20);
}
}
}
????????保存腳本和場景,運行游戲,發(fā)現(xiàn)沒隔2秒就會有一個敵人生成,并且場景中最多會有10個敵人,當(dāng)場景中的敵人數(shù)量少于10個時,又會有新的敵人生成出來,這樣就可以一直玩下去了。文章來源:http://www.zghlxwxcb.cn/news/detail-804401.html
五、結(jié)束語
? ? ? ? 好了,射擊游戲到這里就結(jié)束了,雖然還有很多不足,但作為初學(xué)者的練習(xí)案例,也用到了許多Unity的基礎(chǔ)知識,希望您能夠獲得一些啟發(fā),對您的學(xué)習(xí)有所幫助。您也可以發(fā)揮自己的想想力,完善本案例,比如增加積分、音效等等,使游戲更加豐富。文章來源地址http://www.zghlxwxcb.cn/news/detail-804401.html
到了這里,關(guān)于使用團結(jié)引擎開發(fā)Unity 3D射擊游戲的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!