?????個(gè)人主頁(yè):@元宇宙-秩沅
????? hallo 歡迎 點(diǎn)贊?? 收藏? 留言?? 加關(guān)注?!
????? 本文由 秩沅 原創(chuàng)
????? 收錄于專欄:unityUI專題篇
?通用API實(shí)現(xiàn)抽象行為封裝【五】?
??前言
???
??(A)UML
??(B)需求分析
??(C)行為實(shí)現(xiàn)——炮臺(tái)的自動(dòng)檢測(cè)并攻擊
??????:步驟實(shí)現(xiàn)
1.炮臺(tái)的行為邏輯封裝:旋轉(zhuǎn),觸發(fā)檢測(cè),發(fā)射炮彈及特效
2.檢測(cè)玩家后自動(dòng)瞄準(zhǔn)攻擊
3.玩家扣血,更新血條,觸發(fā)保護(hù)罩特效及死亡
——————————————
涉及到四個(gè)腳本
炮臺(tái)封裝
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 炮臺(tái)的行為邏輯實(shí)現(xiàn)
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class battery : TankFather
{
public AudioSource shootMusic; //發(fā)射音效
public GameObject shootball; //發(fā)射的子彈類型
public float shootSpeed = 1000f; //子彈的速度
public Transform shootTransform; //發(fā)射的組件信息
public bool shootSwitch = false;
//射擊檢測(cè)參數(shù)
public Transform player; //闖入者
private float endTime = 8f; //子彈發(fā)射間隔的時(shí)間
private void Start()
{
//屬性初始化賦值
Head = transform.GetChild(0);
maxBlood = 500;
nowBlood = 500;
attack = 20;
HeadSpeed = 50;
//射擊音效關(guān)閉
shootMusic.enabled = false;
}
private void Update()
{
if (shootSwitch == false) //不停的旋轉(zhuǎn)
{
Head.transform.Rotate(Vector3.up * HeadSpeed * Time.deltaTime);
}
else
{
Head.transform.LookAt(player);
//倒計(jì)時(shí)發(fā)射子彈
endTime = Mathf.MoveTowards(endTime, 0, 0.1f);
if(endTime <= 0)
{
Fire();
endTime = 3f;
}
}
}
//玩家進(jìn)入范圍內(nèi)就開(kāi)始射擊
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
shootSwitch = true;
player = other.transform;
}
}
//受傷檢測(cè)
private void OnTriggerStay(Collider other)
{
float off = Vector3.Distance(other.transform.position, transform.position);
if (other.gameObject.tag == "bullet" && off < 2)
{
//添加子彈掛載的目標(biāo)坦克,方便獲取該子彈的攻擊力,與受傷邏輯相結(jié)合
BulletMove ball = other.gameObject.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//當(dāng)子彈不是自己打的到自己身上的時(shí)候
if (ballTank.tag != gameObject.tag)
{
//扣血
Heart(ballTank);
}
}
}
//玩家出去后就停止射擊
private void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
shootSwitch = false;
}
}
//開(kāi)火重寫(xiě)
public override void Fire()
{
//開(kāi)啟射擊音效
shootMusic.enabled = true;
shootMusic.Play();
GameObject ball = Instantiate(shootball, shootTransform.position , shootTransform.rotation);
BulletMove movScript = ball.GetComponent<BulletMove>();
Rigidbody shootBall = ball.GetComponent<Rigidbody>();
shootBall.AddForce(shootTransform .transform.forward * shootSpeed );
movScript.Tank =gameObject ; //聲明子彈是由誰(shuí)打出去的
}
}
坦克基類更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目:
//___________功能: 坦克基類——集中子類相同點(diǎn)
//___________創(chuàng)建者:______秩沅______
//___________________________________
//-------------------------------------
public abstract class TankFather : MonoBehaviour
{
//攻擊和防御相關(guān)
public int attack;
public int defence;
public float nowBlood;
public float maxBlood;
//移動(dòng)和轉(zhuǎn)速相關(guān)
public int moveSpeed;
public int RotateSpeed;
public int HeadSpeed;
public Transform Head;
//擊敗特效
public GameObject diedEffect;
//收到傷害打開(kāi)保護(hù)罩的特效
public GameObject ProtectEffectMain;
public GameObject ProtectEffectOther;
private void Awake()
{
// ProtectEffectMain = Resources.Load<GameObject>(@"Prefabs/OherResoure/Protect1");
// ProtectEffectOther = Resources.Load<GameObject>(@"Prefabs/OherResoure/Protect2");
}
//受傷行為
public virtual void Heart(TankFather other)
{
//當(dāng)攻擊力大于防御力時(shí)才生效
if (other.attack - defence > 0)
{
nowBlood -= (other.attack - defence);
}
if (nowBlood <= 0)
{
nowBlood = 0;
Death();
}
if (gameObject.tag == "Player")//如果是主玩家才更新血條
{
//更新血條
GamePlane.SingleInstance.UpdataBlood(maxBlood, nowBlood);
//實(shí)例化保護(hù)罩的特效
GameObject eff = Instantiate(ProtectEffectMain, transform.position, transform.rotation);
Destroy(eff,1f);
}
}
//死亡行為
public virtual void Death()
{
//將特效實(shí)例化相關(guān)邏輯
GameObject effect = Instantiate(diedEffect, this.transform.position ,this.transform.rotation);
AudioSource soudClip = effect.GetComponent<AudioSource>();
soudClip.enabled = MusicContol.SingleMusicContol.nowMusicData.soundSwitch;
soudClip.volume = MusicContol.SingleMusicContol.nowMusicData.soundRoll ;
soudClip.mute = false;
soudClip.playOnAwake = true;
//死亡后展示死亡面板
if (gameObject.tag == "Player")
{
Destroy(gameObject, 2F);
DiedPlane.SingleInstance.Show();
}
else
Destroy(gameObject);
}
//開(kāi)火行為
public abstract void Fire(); //子類中每一個(gè)的開(kāi)火方式都不同,作為抽象方法
}
主坦克類更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目:
//___________功能: 坦克的移動(dòng)和旋轉(zhuǎn)
//___________創(chuàng)建者:_______秩沅_______
//_____________________________________
//-------------------------------------
public class MainTank : TankFather
{
//主坦克專有特征
public Weapon nowWeapon;
//特征屬性初始化
private void Awake()
{
Head = transform.GetChild(1).GetChild(0);
maxBlood = 1000;
nowBlood = 1000;
attack = 30;
defence = 10;
moveSpeed = 5;
RotateSpeed = 50;
HeadSpeed = 500;
}
private void Update()
{
//坦克的移動(dòng) = 大小*方向
transform.Translate(Input.GetAxis("Vertical") *Vector3.forward*moveSpeed *Time.deltaTime );
//坦克的旋轉(zhuǎn) = 大小*軸向
transform.Rotate(Input.GetAxis("Horizontal") *Vector3.up *RotateSpeed *Time .deltaTime );
//頭部炮管的旋轉(zhuǎn) = 大小*軸向
Head.Rotate(Input.GetAxis ("Mouse X") *Vector3.up*HeadSpeed*Time .deltaTime );
//左鍵發(fā)射炮彈
if(Input.GetMouseButtonDown(0))
{
Fire();
}
}
//撿武器行為
public void ChangeWeapon(GameObject weapon)
{
if (nowWeapon != null) nowWeapon.Vanish(); //銷毀當(dāng)前武器
nowWeapon = weapon.GetComponent<Weapon>();
//頭部留有存放武器的位置
weapon.gameObject.transform.position = Head.GetChild(0).transform.position ;
weapon.gameObject.transform.rotation = Head.GetChild(0).transform.rotation;
weapon.gameObject.transform.SetParent(Head.GetChild(0));
attack += nowWeapon.attack;
}
//開(kāi)火行為重寫(xiě)
public override void Fire()
{
nowWeapon.Shoot();
}
//被子彈打到
private void OnTriggerEnter(Collider other)
{
if(other.tag == "bullet")
{
try
{
//添加子彈掛載的目標(biāo)坦克,方便獲取該子彈的攻擊力,與受傷邏輯相結(jié)合
BulletMove ball = other.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//當(dāng)子彈不是自己打的到自己身上的時(shí)候
if (ballTank.tag != "Player")
{
//扣血
Heart(ballTank);
}
}
catch
{
throw;
}
}
}
}
子彈發(fā)射更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目: ______________
//___________功能: 子彈的邏輯相關(guān)
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class BulletMove : MonoBehaviour
{
public GameObject Tank; //掛載在哪個(gè)坦克上
public GameObject DeidEffect;
public AudioSource distorySound; //銷毀的音效
private void Start()
{
}
//子彈的銷毀及特效
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Environment")|| other.CompareTag("Enemy"))
{
if (DeidEffect != null)
{
GameObject eff = Instantiate(DeidEffect, transform.position, transform.rotation);
//音效控制
distorySound = eff.GetComponent<AudioSource>();
distorySound.enabled = MusicContol.SingleMusicContol.nowMusicData.soundSwitch;
distorySound.volume = MusicContol.SingleMusicContol.nowMusicData.soundRoll;
eff.AddComponent<SelfDestroy>();
}
Destroy(this.gameObject,2f);
}
}
}
??(D)行為實(shí)現(xiàn)——敵軍坦克的移動(dòng)路線和檢測(cè)攻擊
??????:步驟實(shí)現(xiàn)
- 1.指定移動(dòng)位置,設(shè)置朝向
- 2.行為邏輯封裝。開(kāi)火,受傷
- 3.自動(dòng)檢測(cè)闖入者
———— --------------————
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________項(xiàng)目:
//___________功能:敵方坦克邏輯封裝
//___________創(chuàng)建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class EnemyTank:TankFather
{
//隨機(jī)移動(dòng)點(diǎn)的位置數(shù)組
public Transform[] randomPosition;
//目標(biāo)位置
private Transform target;
//目標(biāo)坦克
public Transform Player;
//檢測(cè)范圍
public float distance = 10f;
public AudioSource shootMusic; //發(fā)射音效
public GameObject shootball; //發(fā)射的子彈類型
public float shootSpeed = 1000f; //子彈的速度
public Transform[] shootTransform; //發(fā)射的組件信息
public bool shootSwitch = false;
private float endTime = 3f; //子彈發(fā)射間隔的時(shí)間
private void Start()
{
//屬性初始化賦值
maxBlood = 500;
nowBlood = 500;
attack = 30;
HeadSpeed = 50;
//射擊音效關(guān)閉
shootMusic.enabled = false;
moveSpeed = 10f;
//先隨機(jī)整一個(gè)目標(biāo)點(diǎn)
RandomPosition();
}
private void Update()
{
transform.LookAt(target);
//始終超自己的正方向移動(dòng)
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); //當(dāng)距離差不多相等時(shí),再隨機(jī)目標(biāo)點(diǎn)
if(Vector3.Distance(transform .position ,target .position)< 0.5f)
{
RandomPosition();
}
//范圍檢測(cè)
if (Vector3 .Distance(transform .position ,Player.position )<= distance && Player !=null )
{
//炮口瞄準(zhǔn)玩家
Head.transform.LookAt(Player);
//倒計(jì)時(shí)發(fā)射子彈
endTime = Mathf.MoveTowards(endTime, 0, 0.1f);
if (endTime <= 0)
{
Fire();
endTime = 3f;
}
}
}
//隨機(jī)指向一個(gè)移動(dòng)點(diǎn)
public void RandomPosition()
{
if (randomPosition.Length != 0)
target = randomPosition[Random.Range(0, randomPosition.Length)];
}
//觸發(fā)檢測(cè)
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "bullet" )
{
//添加子彈掛載的目標(biāo)坦克,方便獲取該子彈的攻擊力,與受傷邏輯相結(jié)合
BulletMove ball = other.gameObject.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//當(dāng)子彈不是自己打的到自己身上的時(shí)候
if (ballTank.tag != gameObject.tag)
{
//扣血
Heart(ballTank);
}
}
}
public override void Fire()
{
//開(kāi)啟射擊音效
shootMusic.enabled = true;
shootMusic.Play();
for (int i = 0; i < shootTransform.Length ; i++)
{
GameObject ball = Instantiate(shootball, shootTransform[i].position, shootTransform[i].rotation);
BulletMove movScript = ball.GetComponent<BulletMove>();
Rigidbody shootBall = ball.GetComponent<Rigidbody>();
shootBall.AddForce(shootTransform[i].transform.forward * shootSpeed);
movScript.Tank = gameObject; //聲明子彈是由誰(shuí)打出去的
}
}
}
問(wèn)題:
1.受到傷害,開(kāi)啟了保護(hù)罩但是不扣血
2.敵方坦克,原地打轉(zhuǎn),未按規(guī)定路線移動(dòng)
解決:
1.子彈檢測(cè)邏輯錯(cuò)誤
2.位置空點(diǎn)綁定在對(duì)象身上變成了子對(duì)象因此無(wú)法達(dá)到效果
總結(jié):
- 1.檢測(cè)觸發(fā)的方式:①觸發(fā)器檢測(cè)②向量距離檢測(cè)
- 2.多點(diǎn)指定移動(dòng),加入向量距離判斷,重合的機(jī)率小,故此不能 A物體距離 == B物體距離
- 3.子坦克繼承了父類腳本,引用傳遞時(shí)直接用父類即可獲得該子類,(原因父類名字相同,但是子類名字不同,無(wú)法確定,所以里氏替換作用在此體現(xiàn))
?相關(guān)文章?
?【2023unity游戲制作-mango的冒險(xiǎn)】-6.關(guān)卡設(shè)計(jì)
?【2023unity游戲制作-mango的冒險(xiǎn)】-5.攻擊系統(tǒng)的簡(jiǎn)單實(shí)現(xiàn)
?【2023unity游戲制作-mango的冒險(xiǎn)】-4.場(chǎng)景二的鏡頭和法球特效跟隨
?【2023unity游戲制作-mango的冒險(xiǎn)】-3.基礎(chǔ)動(dòng)作和動(dòng)畫(huà)API實(shí)現(xiàn)
?【2023unity游戲制作-mango的冒險(xiǎn)】-2.始畫(huà)面API制作
?【2023unity游戲制作-mango的冒險(xiǎn)】-1.場(chǎng)景搭建
?“狂飆”游戲制作—游戲分類圖鑒(網(wǎng)易游學(xué))
?本站最全-unity常用API大全(萬(wàn)字詳解),不信你不收藏文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-612565.html
你們的點(diǎn)贊?? 收藏? 留言?? 關(guān)注?是我持續(xù)創(chuàng)作,輸出優(yōu)質(zhì)內(nèi)容的最大動(dòng)力!文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-612565.html
到了這里,關(guān)于【unity之IMGUI實(shí)踐】敵方邏輯封裝實(shí)現(xiàn)【六】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!