👨💻个人主页:@元宇宙-秩沅
👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅!
👨💻 本文由 秩沅 原创
👨💻 收录于专栏:unityUI专题篇
⭐通用API实现抽象行为封装【五】⭐
🎶前言
🅰️
🎶(A)UML
🎶(B)需求分析
🎶(C)行为实现——炮台的自动检测并攻击
😶🌫️:步骤实现
1.炮台的行为逻辑封装:旋转,触发检测,发射炮弹及特效
2.检测玩家后自动瞄准攻击
3.玩家扣血,更新血条,触发保护罩特效及死亡
——————————————
涉及到四个脚本
炮台封装
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 炮台的行为逻辑实现
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class battery : TankFather
{
public AudioSource shootMusic; //发射音效
public GameObject shootball; //发射的子弹类型
public float shootSpeed = 1000f; //子弹的速度
public Transform shootTransform; //发射的组件信息
public bool shootSwitch = false;
//射击检测参数
public Transform player; //闯入者
private float endTime = 8f; //子弹发射间隔的时间
private void Start()
{
//属性初始化赋值
Head = transform.GetChild(0);
maxBlood = 500;
nowBlood = 500;
attack = 20;
HeadSpeed = 50;
//射击音效关闭
shootMusic.enabled = false;
}
private void Update()
{
if (shootSwitch == false) //不停的旋转
{
Head.transform.Rotate(Vector3.up * HeadSpeed * Time.deltaTime);
}
else
{
Head.transform.LookAt(player);
//倒计时发射子弹
endTime = Mathf.MoveTowards(endTime, 0, 0.1f);
if(endTime <= 0)
{
Fire();
endTime = 3f;
}
}
}
//玩家进入范围内就开始射击
private void OnTriggerEnter(Collider other)
{
if(other.tag == "Player")
{
shootSwitch = true;
player = other.transform;
}
}
//受伤检测
private void OnTriggerStay(Collider other)
{
float off = Vector3.Distance(other.transform.position, transform.position);
if (other.gameObject.tag == "bullet" && off < 2)
{
//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合
BulletMove ball = other.gameObject.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//当子弹不是自己打的到自己身上的时候
if (ballTank.tag != gameObject.tag)
{
//扣血
Heart(ballTank);
}
}
}
//玩家出去后就停止射击
private void OnTriggerExit(Collider other)
{
if (other.tag == "Player")
{
shootSwitch = false;
}
}
//开火重写
public override void Fire()
{
//开启射击音效
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 ; //声明子弹是由谁打出去的
}
}
坦克基类更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能: 坦克基类——集中子类相同点
//___________创建者:______秩沅______
//___________________________________
//-------------------------------------
public abstract class TankFather : MonoBehaviour
{
//攻击和防御相关
public int attack;
public int defence;
public float nowBlood;
public float maxBlood;
//移动和转速相关
public int moveSpeed;
public int RotateSpeed;
public int HeadSpeed;
public Transform Head;
//击败特效
public GameObject diedEffect;
//收到伤害打开保护罩的特效
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)
{
//当攻击力大于防御力时才生效
if (other.attack - defence > 0)
{
nowBlood -= (other.attack - defence);
}
if (nowBlood <= 0)
{
nowBlood = 0;
Death();
}
if (gameObject.tag == "Player")//如果是主玩家才更新血条
{
//更新血条
GamePlane.SingleInstance.UpdataBlood(maxBlood, nowBlood);
//实例化保护罩的特效
GameObject eff = Instantiate(ProtectEffectMain, transform.position, transform.rotation);
Destroy(eff,1f);
}
}
//死亡行为
public virtual void Death()
{
//将特效实例化相关逻辑
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);
}
//开火行为
public abstract void Fire(); //子类中每一个的开火方式都不同,作为抽象方法
}
主坦克类更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能: 坦克的移动和旋转
//___________创建者:_______秩沅_______
//_____________________________________
//-------------------------------------
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()
{
//坦克的移动 = 大小*方向
transform.Translate(Input.GetAxis("Vertical") *Vector3.forward*moveSpeed *Time.deltaTime );
//坦克的旋转 = 大小*轴向
transform.Rotate(Input.GetAxis("Horizontal") *Vector3.up *RotateSpeed *Time .deltaTime );
//头部炮管的旋转 = 大小*轴向
Head.Rotate(Input.GetAxis ("Mouse X") *Vector3.up*HeadSpeed*Time .deltaTime );
//左键发射炮弹
if(Input.GetMouseButtonDown(0))
{
Fire();
}
}
//捡武器行为
public void ChangeWeapon(GameObject weapon)
{
if (nowWeapon != null) nowWeapon.Vanish(); //销毁当前武器
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;
}
//开火行为重写
public override void Fire()
{
nowWeapon.Shoot();
}
//被子弹打到
private void OnTriggerEnter(Collider other)
{
if(other.tag == "bullet")
{
try
{
//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合
BulletMove ball = other.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//当子弹不是自己打的到自己身上的时候
if (ballTank.tag != "Player")
{
//扣血
Heart(ballTank);
}
}
catch
{
throw;
}
}
}
}
子弹发射更新
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目: ______________
//___________功能: 子弹的逻辑相关
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class BulletMove : MonoBehaviour
{
public GameObject Tank; //挂载在哪个坦克上
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)行为实现——敌军坦克的移动路线和检测攻击
😶🌫️:步骤实现
- 1.指定移动位置,设置朝向
- 2.行为逻辑封装。开火,受伤
- 3.自动检测闯入者
———— --------------————
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//-------------------------------------
//—————————————————————————————————————
//___________项目:
//___________功能:敌方坦克逻辑封装
//___________创建者:秩沅_______________
//_____________________________________
//-------------------------------------
public class EnemyTank:TankFather
{
//随机移动点的位置数组
public Transform[] randomPosition;
//目标位置
private Transform target;
//目标坦克
public Transform Player;
//检测范围
public float distance = 10f;
public AudioSource shootMusic; //发射音效
public GameObject shootball; //发射的子弹类型
public float shootSpeed = 1000f; //子弹的速度
public Transform[] shootTransform; //发射的组件信息
public bool shootSwitch = false;
private float endTime = 3f; //子弹发射间隔的时间
private void Start()
{
//属性初始化赋值
maxBlood = 500;
nowBlood = 500;
attack = 30;
HeadSpeed = 50;
//射击音效关闭
shootMusic.enabled = false;
moveSpeed = 10f;
//先随机整一个目标点
RandomPosition();
}
private void Update()
{
transform.LookAt(target);
//始终超自己的正方向移动
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); //当距离差不多相等时,再随机目标点
if(Vector3.Distance(transform .position ,target .position)< 0.5f)
{
RandomPosition();
}
//范围检测
if (Vector3 .Distance(transform .position ,Player.position )<= distance && Player !=null )
{
//炮口瞄准玩家
Head.transform.LookAt(Player);
//倒计时发射子弹
endTime = Mathf.MoveTowards(endTime, 0, 0.1f);
if (endTime <= 0)
{
Fire();
endTime = 3f;
}
}
}
//随机指向一个移动点
public void RandomPosition()
{
if (randomPosition.Length != 0)
target = randomPosition[Random.Range(0, randomPosition.Length)];
}
//触发检测
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "bullet" )
{
//添加子弹挂载的目标坦克,方便获取该子弹的攻击力,与受伤逻辑相结合
BulletMove ball = other.gameObject.GetComponent<BulletMove>();
TankFather ballTank = ball.Tank.GetComponent<TankFather>();
//当子弹不是自己打的到自己身上的时候
if (ballTank.tag != gameObject.tag)
{
//扣血
Heart(ballTank);
}
}
}
public override void Fire()
{
//开启射击音效
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; //声明子弹是由谁打出去的
}
}
}
问题:
1.受到伤害,开启了保护罩但是不扣血
2.敌方坦克,原地打转,未按规定路线移动
解决:
1.子弹检测逻辑错误
2.位置空点绑定在对象身上变成了子对象因此无法达到效果
总结:
- 1.检测触发的方式:①触发器检测②向量距离检测
- 2.多点指定移动,加入向量距离判断,重合的机率小,故此不能 A物体距离 == B物体距离
- 3.子坦克继承了父类脚本,引用传递时直接用父类即可获得该子类,(原因父类名字相同,但是子类名字不同,无法确定,所以里氏替换作用在此体现)
⭐相关文章⭐
⭐【2023unity游戏制作-mango的冒险】-6.关卡设计
⭐【2023unity游戏制作-mango的冒险】-5.攻击系统的简单实现
⭐【2023unity游戏制作-mango的冒险】-4.场景二的镜头和法球特效跟随
⭐【2023unity游戏制作-mango的冒险】-3.基础动作和动画API实现
⭐【2023unity游戏制作-mango的冒险】-2.始画面API制作
⭐【2023unity游戏制作-mango的冒险】-1.场景搭建
⭐“狂飙”游戏制作—游戏分类图鉴(网易游学)
⭐本站最全-unity常用API大全(万字详解),不信你不收藏文章来源:https://www.toymoban.com/news/detail-612565.html
你们的点赞👍 收藏⭐ 留言📝 关注✅是我持续创作,输出优质内容的最大动力!文章来源地址https://www.toymoban.com/news/detail-612565.html
到了这里,关于【unity之IMGUI实践】敌方逻辑封装实现【六】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!