本節(jié)最終效果
前言
本節(jié)緊跟著上一篇,主要實現(xiàn)對象池程序化生成敵人和屬性配置。
敵人追擊玩家
新增不同敵人預(yù)制體,并配置默認跑步動畫
新增一個敵人類的腳本,實現(xiàn)了敵人向玩家移動并面對玩家的功能。注釋已添加在相應(yīng)的代碼行上。
public class Enemy : MonoBehaviour
{
public float speed; // 移動速度
public Rigidbody2D target; // 目標(玩家)
bool isLive = true; // 是否存活
Rigidbody2D rigid; // 剛體組件
SpriteRenderer spriter; // 精靈渲染器組件
void Awake()
{
rigid = GetComponent<Rigidbody2D>();
spriter = GetComponent<SpriteRenderer>();
}
private void Start() {
target = GameManager.instance.player.GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
if(!isLive) return;
// 根據(jù)目標的位置和自身的位置決定是否翻轉(zhuǎn)精靈
spriter.flipX = (target.position.x < rigid.position.x);
// 計算目標位置和當前位置之間的方向向量
Vector2 dirVec = target.position - rigid.position;
// 計算下一幀移動的位置向量,保持單位長度并乘以速度和固定時間步長
Vector2 nextVec = dirVec.normalized * speed * Time.fixedDeltaTime;
// 移動到下一幀位置
rigid.MovePosition(rigid.position + nextVec);
}
}
掛載腳本,配置參數(shù),一般敵人移速都是比主角低
我們放幾個敵人到場景進行測試,效果
處理超出游戲區(qū)域的敵人
因為敵人的移速肯定比主角慢,主角一直往前走,如果我們不做處理,后面的敵人會越來越多,而且超出了屏幕,這部分的敵人對我們來說是沒有意義的,而且還占用資源,我們可以復(fù)用前面的Reposition代碼,超出游戲區(qū)域,重新定位敵人對象的位置瞬移到角色前面。
修改Reposition
Collider2D coll;
private void Awake()
{
coll = GetComponent<Collider2D>();
}
// 當碰撞體離開觸發(fā)器時調(diào)用
void OnTriggerExit2D(Collider2D collision)
{
//...
// 根據(jù)自身的標簽進行不同的處理
switch (transform.tag)
{
//...
// 如果自身是"Enemy"標簽,重新定位敵人對象的位置,以確保它不會超出游戲區(qū)域。
case "Enemy":
if (coll.enabled)
{
Vector3 dist = playerPos - myPos;
Vector3 ran = new Vector3(Random.Range(-3f, 3f), Random.Range(-3f, 3f), 0);
transform.Translate(ran + dist * 2);
}
break;
}
}
敵人掛載腳本,并配置Enemy標簽
效果
定義對象池
對象池介紹:【Unity小技巧】Unity探究自制對象池和官方內(nèi)置對象池(ObjectPool)的使用
新增對象池腳本PoolManager
public class PoolManager : MonoBehaviour
{
public GameObject[] prefabs; // 預(yù)制體數(shù)組
List<GameObject>[] pools; // 對象池數(shù)組
void Awake()
{
// 初始化對象池數(shù)組
pools = new List<GameObject>[prefabs.Length];
for (int index = 0; index < pools.Length; index++)
{
pools[index] = new List<GameObject>();
}
Debug.Log(pools.Length);
}
public GameObject Get(int index)
{
GameObject select = null;
// 在對象池中查找未激活的對象
foreach (GameObject item in pools[index])
{
if (!item.activeSelf)
{
// 如果找到未激活的對象,選擇它并激活
select = item;
select.SetActive(true);
break;
}
}
// 如果對象池中沒有未激活的對象,則創(chuàng)建一個新對象
if (!select)
{
select = Instantiate(prefabs[index], transform);
pools[index].Add(select);
}
// 返回選擇的對象
return select;
}
}
掛載腳本,配置敵人預(yù)制體
修改GameManager,綁定對象池
public PoolManager pool; // 對象池
掛載參數(shù)
使用對象池生成敵人
新增Spawner 敵人生成器類的腳本,用于在不同的出生點上生成敵人。
public class Spawner : MonoBehaviour
{
public Transform[] spawnPoints; // 出生點數(shù)組
float timer;
void Awake()
{
spawnPoints = GetComponentsInChildren<Transform>();
}
void Update()
{
timer += Time.deltaTime;
if (timer >= 0.2f)
{
timer = 0;
Spawn();
}
}
void Spawn()
{
// 從對象池中獲取敵人
GameObject enemy = GameManager.instance.pool.Get(Random.Range(0, 5));
// 設(shè)置敵人的位置為隨機選擇的出生點
enemy.transform.position = spawnPoints[Random.Range(1, spawnPoints.Length)].position;
}
}
添加敵人生成點位置
掛載配置參數(shù)
效果
隨時間推移生成不同屬性的敵人,提升難度
修改GameManager
public float gameTime; // 游戲時間
public float maxGameTime = 100f; // 最大游戲時間
void Update()
{
gameTime += Time.deltaTime; // 更新游戲時間
// 將游戲時間限制在最大游戲時間內(nèi)
if (gameTime >= maxGameTime) gameTime = maxGameTime;
}
修改Spawner
int level;
public SpawnData[] spawnData;//生成物體的數(shù)據(jù)配置
void Update()
{
level = Mathf.Min(Mathf.FloorToInt(GameManager.instance.gameTime / 10f), spawnData.Length - 1);
timer += Time.deltaTime;
if (timer > spawnData[level].spawnTime)
{
timer = 0;
Spawn();
}
}
void Spawn()
{
// 從對象池中獲取敵人
GameObject enemy = GameManager.instance.pool.Get(0);
// 設(shè)置敵人的位置為隨機選擇的出生點
enemy.transform.position = spawnPoints[Random.Range(1, spawnPoints.Length)].position;
enemy.GetComponent<Enemy>().Init(spawnData[level]);
}
//用于存儲生成物體的數(shù)據(jù)
[System.Serializable]
public class SpawnData
{
public int spriteType; // 精靈索引
public float spawnTime;// 生成時間
public int health;// 生命值
public float speed;// 速度
}
配置每一種怪物的屬性值
修改Enemy,根據(jù)參數(shù),動態(tài)配置敵人動畫和血量
Animator anim;
public float health;//當前生命值
public float maxHealth;//最大生命值
public RuntimeAnimatorController[] animCon;// 不同類型精靈的動畫控制器
void Awake()
{
//。。。
anim = GetComponent<Animator>();
}
private void Start()
{
target = GameManager.instance.player.GetComponent<Rigidbody2D>();
isLive = true;
health = maxHealth;
}
//初始化敵人的屬性和狀態(tài)
public void Init(SpawnData data)
{
// 根據(jù)生成數(shù)據(jù)設(shè)置敵人的動畫控制器、速度、最大生命值和當前生命值
anim.runtimeAnimatorController = animCon[data.spriteType];
speed = data.speed;
maxHealth = data.health;
health = data.health;
}
保留一個敵人預(yù)制體即可,配置不同的敵人動畫控制器參數(shù)
當然,對象池也保留一個敵人配置
效果,每過10秒生成下一種敵人,召喚不同等級的怪物
參考
【視頻】https://www.youtube.com/watch?v=MmW166cHj54&list=PLO-mt5Iu5TeZF8xMHqtT_DhAPKmjF6i3x
源碼
源碼在最后一節(jié)
完結(jié)
贈人玫瑰,手有余香!如果文章內(nèi)容對你有所幫助,請不要吝嗇你的點贊評論和關(guān)注
,以便我第一時間收到反饋,你的每一次支持
都是我不斷創(chuàng)作的最大動力。當然如果你發(fā)現(xiàn)了文章中存在錯誤
或者有更好的解決方法
,也歡迎評論私信告訴我哦!
好了,我是向宇
,https://xiangyu.blog.csdn.net文章來源:http://www.zghlxwxcb.cn/news/detail-840592.html
一位在小公司默默奮斗的開發(fā)者,出于興趣愛好,于是最近才開始自習unity。如果你遇到任何問題,也歡迎你評論私信找我, 雖然有些問題我可能也不一定會,但是我會查閱各方資料,爭取給出最好的建議,希望可以幫助更多想學編程的人,共勉~文章來源地址http://www.zghlxwxcb.cn/news/detail-840592.html
到了這里,關(guān)于【用unity實現(xiàn)100個游戲之17】從零開始制作一個類幸存者肉鴿(Roguelike)游戲2(附項目源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!