太空大战–敌人创建

前言

该博客为记录学习太空大战unity项目的过程。

游戏介绍

在游戏中,主角操作太空飞船和敌人的太空飞船战斗。消灭敌人的飞船可以取得一定的分数,游戏没有尽头,如果主角的飞船被击落,则游戏结束。

创建敌人

将文件中的Enemy.fbx模型文件拖入到Hierachy视图中
新建Enemy.cs,并添加代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour
{//敌人的速度public float m_speed = 1.0f;//敌人的生命public int m_life = 10;//获取敌人的transform组件protected Transform m_transform;// Start is called before the first frame updatevoid Start(){m_transform = this.transform;}// Update is called once per framevoid Update(){UpdateMove();}protected virtual void UpdateMove(){//让敌人左右移动float rx = Mathf.Sin(Time.time) * Time.deltaTime;//让敌人朝主角方向前进m_transform.Translate(new Vector3(rx, 0, -m_speed * Time.deltaTime));}
}

指定Enemy.cs为Enemy游戏的脚本组件。
根据创建子弹prefab的方式一样创建Enemy.prefab文件。

物理碰撞

选择Enemy模型,在Inspector视图中选择Component->Physics->RigidBody。为敌人添加一个刚体组件。所有需要物理组件的模型都需要一个刚体组件才可以正常的工作。

在RigidBody组件中,取消选中Use Gravity使模型不受重力影响。然后选中Is Kinematic使模型的运动不受物理模拟影响。

选择Enemy模型,在Inspector视图中选择Component->Physics->Box Collider。为敌人添加一个立方体碰撞组件。

在Box Collider组件中,选中Is Trigger,使其具有触发作用。

同理,给子弹和主角游戏体添加物理组件。

触发碰撞

选择Edit->Project Settings->Tags and Layers。
选择tags右下角的加号来添加标签。

先添加两个标签Enemy和PlayerRocket

选择Player模型,在Inspector视图中把tag设置为Player,Player标签是Unity自带的。

同理设置Rocket和Enemy的标签为PlayerRocket和Enemy。
打开Enemy.cs,修改代码如下。
1、添加一个OnTriggerEnter函数。在碰撞体互相碰撞时触发。

void OnTriggerEnter(Collider other)
{//如果撞到的是主角子弹if (other.tag == "PlayerRocket") {//获取该子弹的Rocket属性Rocket rocket = other.GetComponent<Rocket>();if(rocket != null){m_life -= rocket.m_power;if (m_life <= 0){Destroy(this.gameObject);}}}//如果撞到的是主角飞船else if(other.tag == "Player"){Destroy(this.gameObject);}
}

打开Rocket.cs,修改代码如下。
1、添加一个OnTriggerEnter函数

void OnTriggerEnter(Collider other)
{if(other.tag != "Enemy"){return;}Destroy(this.gameObject);
}

打开Player.cs,修改代码如下。
1、添加一个主角生命属性

public int m_life = 3;

2、添加一个OnTriggerEnter函数,让他撞到敌人时生命值-1


void OnTriggerEnter(Collider other)
{if(other.tag != "PlayerRocket"){m_life -= 1;if(m_life <= 0){Destroy(this.gameObject);}}
}

打开Enemy.cs,修改代码如下。
1、添加代码,防止敌人为被即使杀死而一直存活,当敌人移动到屏幕外则删除敌人游戏体

//获取敌人的Renderer组件
internal Renderer m_renderer;//判断是否激活
internal bool m_isActiv = false;// Start is called before the first frame update
void Start()
{m_transform = this.transform;m_renderer = GetComponent<Renderer>();
}private void OnBecameVisible()
{m_isActiv = true;
}// Update is called once per frame
void Update()
{UpdateMove();if(m_isActiv && !m_renderer.isVisible){Destroy(this.gameObject);}
}

高级敌人

将文件中的Enemy2b.fbx模型文件拖入到Hie视图当中去。
该模型有两个文件,一个为碰撞模型,另一个是游戏中的显示模型。

选中Enemy2b游戏体,按照上面的步骤给Enemy2b添加RigidBody组件。
选中Enemy2b的碰撞模型col,在菜单栏上选择Component->Physics->Mesh Collider添加Mesh碰撞体。 选中Enemy2b的碰撞模型col,取消选中它的Mesh Render组件,这样在游戏中就不会显示出它的碰撞模型。

选中Enemy2b游戏体,选择它的tag为Enemy。
创建SuperEnemy.cs,添加代码如下。
1、继承父类Enemy,并重写MoveUpdate方法。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SuperEnemy : Enemy
{// Start is called before the first frame update// 重写父类中的MoveUpdate方法protected override void UpdateMove(){//朝着主角方向前进transform.Translate(new Vector3(0, 0, -m_speed * Time.deltaTime));}
}

将SuperEnemy.cs指定给Enemy2b的脚本组件。
创建EnemyRender.cs,并添加代码如下。
1、添加代码,来获取子一级的Renderer组件属性。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyRender : MonoBehaviour
{// Start is called before the first frame update//获取Enemypublic Enemy m_enemy;void Start(){m_enemy = this.GetComponentInParent<Enemy>();    }private void OnBecameVisible(){//因为Enemy2b没有Renderer组件,所以当调用GetComponet<Renderer>时会返回空值//所以只能获取子物件的Renderer组件属性当作自己的Renderer组件//该代码中是通过把子物件中的Render组件给父物件m_enemy.m_isActiv = true;m_enemy.m_renderer = this.GetComponent<Renderer>();}
}

将EnemyRender.cs指定为Enemy2b层级下的Enemy2的脚本组件。
按照之前制作Enemy.prefab文件同样的方式,制作SuperEnemy.prefab组件。

发射子弹

在Material中新建一个材质球,并命名为Rocket。
将Rocket2.png作为贴图。

将文件中的Rocket.fbx模型文件拖入到Hierarchy视图中,并将其Rename为EnemyRocket。
选中EnemyRocket游戏体,选择替换原本的Material成Rocket2材质球。
按照之前创建tag的方式,新建一个叫做EnemyRocket的tag,并修改EnemyRocket游戏体的tag为EnemyRocket。
选中EnemyRocket,按照上面的方式给它添加RigidBody组件和Box Collide组件。
按照上面的方式将EnemyRocket制作成EnemyRocket.prefab文件
新建EnemyRocket.cs,修改代码如下。
1、添加代码,让他继承父类Rocket
2、添加OnTriggerEnter函数,使它碰撞到玩家游戏体时触发效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyRocket : Rocket
{private void OnTriggerEnter(Collider other){if(other.tag != "Player"){return;}Destroy(this.gameObject);}
}

将EnemyRocke.cst指定为EnemyRocket游戏体的脚本组件。
将EnemyRocket按照上面的方式制作成EnemyRocket.prefab文件。
打开SuperEnemy.cs,添加代码如下。
1、修改代码,添加一个控制敌人发射子弹频率的属性

//开火频率
protected float m_fireTimer = 2;

2、修改代码,添加一个获取子弹prefab的属性

//获取子弹属性
public Transform m_rocket;

3、修改代码,添加一个获取Player组件的代码

//获取主角属性
protected Transform m_player;

4、修改UpdateMove函数,添加能让他每隔一段时间就自动发射子弹的代码

protected override void UpdateMove()
{//朝着主角方向前进transform.Translate(new Vector3(0, 0, -m_speed * Time.deltaTime));m_fireTimer -= Time.deltaTime;if(m_fireTimer <= 0){m_fireTimer = 2;if(m_player != null){//使用向量减法来获取朝向主角的向量方向Vector3 v = m_player.transform.position - transform.position;Instantiate(m_rocket, transform.position, Quaternion.LookRotation(v));}else{GameObject obj = GameObject.FindGameObjectWithTag("Player");if(obj != null){m_player = obj.transform;}}}
}

选择EnemyRocket.prefab文件将他与SuperEnemy中的m_rocket绑定。

小兵生成器

在Hierarchy视图中选择Create->Create Empty创建两个个空的游戏体EnemySpawn和SuperEnemySpawn
创建EnemySpawn.cs,添加代码如下。
1、添加代码使其能够自动创建敌人。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemySpawn : MonoBehaviour
{// Start is called before the first frame updatepublic Transform m_enemy;void Start(){StartCoroutine(SpawnEnemy());}//使用协程创建敌人IEnumerator SpawnEnemy(){while(true){yield return new WaitForSeconds(Random.Range(5, 15));   //随机等待5-15秒Instantiate(m_enemy, transform.position, Quaternion.identity);  //生成敌人实例}}
}

2、添加函数OnDrawGizmos函数,该函数的作用是可以Scene视图显示图片,却不会在Game视图中显示。这样方便我们摆放。图片的位置一定要放在Gizmos文件夹中。

private void OnDrawGizmos()
{Gizmos.DrawIcon(transform.position, "item.png", true)
}

指定EnemyPawn.cs为EnemyPawn游戏体和SuperEnemyPawn游戏体的脚本组件。
将enemy.prefab和EnemyPawn游戏体的m_enemy绑定。
将superenemy.prefab和SuperEnemyPawn游戏体的m_enemy绑定。

运行效果

图片一直上传失败。。。

完整的Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour
{//控制飞行速度public float m_speed = 1;//获取transform游戏组件Transform m_transform;//用来获取子弹的prefabpublic Transform m_rocket;//用来控制子弹的发射频率float m_rocketTime = 0;//主角生命public int m_life = 3;//声音源protected AudioSource m_audio;//子弹发射声音文件public AudioClip m_shootClip;//爆炸特效public Transform m_explosionFX;// Start is called before the first frame updatevoid Start(){m_transform = this.transform;//获取声音源组件m_audio = GetComponent<AudioSource>();}// Update is called once per framevoid Update(){//x轴方向移动的距离float moveh = 0;//z轴方向移动的距离float movev = 0;if (Input.GetKey(KeyCode.UpArrow)){movev += Time.deltaTime * m_speed;}if (Input.GetKey(KeyCode.DownArrow)){movev -= Time.deltaTime * m_speed;}if (Input.GetKey(KeyCode.LeftArrow)){moveh -= Time.deltaTime * m_speed;}if(Input.GetKey(KeyCode.RightArrow)){moveh += Time.deltaTime * m_speed;}m_transform.Translate(new Vector3(moveh, 0, movev));m_rocketTime -= Time.deltaTime;if(m_rocketTime <= 0){m_rocketTime = 0.1f; //控制发射频率为隔0.1秒可以发射一次//按住空格键或者鼠标左键可以发射子弹if(Input.GetKey(KeyCode.Space) || Input.GetMouseButton(0)){//创建子弹实例Instantiate(m_rocket, m_transform.position, m_transform.rotation);//播放声音m_audio.PlayOneShot(m_shootClip);}}}private void OnTriggerEnter(Collider other){if(other.tag != "PlayerRocket"){m_life -= 1;GameManager.instance.changeLife(m_life);if(m_life <= 0){Destroy(this.gameObject);Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);}}}
}

完整的Rocket.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Rocket : MonoBehaviour
{// Start is called before the first frame update//子弹飞行的速度public float m_speed = 10;//子弹的威力public int m_power = 1;//获取该模型的transform组件protected Transform m_transform;//当可渲染的物体离开视角范围则自动调用该函数private void OnBecameInvisible(){if(this.enabled)    //通过判断是否处于激活状态防止重复删除{Destroy(this.gameObject);}}void Start(){m_transform = this.transform;}// Update is called once per framevoid Update(){this.transform.Translate(new Vector3(0, 0, Time.deltaTime * m_speed));}void OnTriggerEnter(Collider other){if(other.tag != "Enemy"){return;}Debug.Log("get it");Destroy(this.gameObject);}
}

完整的Enemy.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour
{//敌人的速度public float m_speed = 1.0f;//敌人的生命public int m_life = 10;//获取敌人的transform组件Transform m_transform;//获取敌人的Renderer组件internal Renderer m_renderer;//判断是否激活internal bool m_isActiv = false;//声音源protected AudioSource m_audio;//爆炸特效public Transform m_explosionFX;//消灭之后获取的分数public int m_point = 10;// Start is called before the first frame updatevoid Start(){m_transform = this.transform;m_renderer = GetComponent<Renderer>();m_audio = GetComponent<AudioSource>();}private void OnBecameVisible(){m_isActiv = true;}// Update is called once per framevoid Update(){UpdateMove();if(m_isActiv && !m_renderer.isVisible){Destroy(this.gameObject);}}protected virtual void UpdateMove(){//让敌人左右移动float rx = Mathf.Sin(Time.time) * Time.deltaTime;//让敌人朝主角方向前进m_transform.Translate(new Vector3(rx, 0, -m_speed * Time.deltaTime));}void OnTriggerEnter(Collider other){//如果撞到的是主角子弹if (other.tag == "PlayerRocket") {//获取该子弹的Rocket属性Rocket rocket = other.GetComponent<Rocket>();if(rocket != null){m_life -= rocket.m_power;if (m_life <= 0){               Destroy(this.gameObject);Instantiate(m_explosionFX, m_transform.position, Quaternion.identity);GameManager.instance.AddScore(m_point);}}}//如果撞到的是主角飞船else if(other.tag == "Player"){Destroy(this.gameObject);}}
}

完整的SuperEnemy.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SuperEnemy : Enemy
{// Start is called before the first frame update// 重写父类中的MoveUpdate方法//开火频率protected float m_fireTimer = 2;//获取主角属性protected Transform m_player;//获取子弹属性public Transform m_rocket;//子弹发射声音文件public AudioClip m_shootClip;protected override void UpdateMove(){//朝着主角方向前进transform.Translate(new Vector3(0, 0, -m_speed * Time.deltaTime));m_fireTimer -= Time.deltaTime;if(m_fireTimer <= 0){m_fireTimer = 2;if(m_player != null){//使用向量减法来获取朝向主角的向量方向Vector3 v = m_player.transform.position - transform.position;Instantiate(m_rocket, transform.position, Quaternion.LookRotation(v));//播放声音文件m_audio.PlayOneShot(m_shootClip);}else{GameObject obj = GameObject.FindGameObjectWithTag("Player");if(obj != null){m_player = obj.transform;}}}}
}

完整的EnemyRender.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyRender : MonoBehaviour
{// Start is called before the first frame update//获取Enemypublic Enemy m_enemy;void Start(){m_enemy = this.GetComponentInParent<Enemy>();    }void OnBecameVisible(){//因为Enemy2b没有Renderer组件,所以当调用GetComponet<Renderer>时会返回空值//所以只能获取子物件的Renderer组件属性当作自己的Renderer组件m_enemy.m_isActiv = true;m_enemy.m_renderer = this.GetComponent<Renderer>();}
}

完整的EnemyRocket.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemyRocket : Rocket
{void OnTriggerEnter(Collider other){if(other.tag == "Player"){Destroy(this.gameObject);}}
}

完整的EnemySpawn.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class EnemySpawn : MonoBehaviour
{// Start is called before the first frame updatepublic Transform m_enemy;void Start(){StartCoroutine(SpawnEnemy());}//使用协程创建敌人IEnumerator SpawnEnemy(){while(true){yield return new WaitForSeconds(Random.Range(5, 15));   //随机等待5-15秒Instantiate(m_enemy, transform.position, Quaternion.identity);  //生成敌人实例}}private void OnDrawGizmos(){Gizmos.DrawIcon(transform.position, "item.png", true);}
}

太空大战--敌人创建相关推荐

  1. 太空大战--场景创建

    太空大战–场景创建 前言 该博客为记录学习太空大战unity项目的过程. 游戏介绍 在游戏中,主角操作太空飞船和敌人的太空飞船战斗.消灭敌人的飞船可以取得一定的分数,游戏没有尽头,如果主角的飞船被击落 ...

  2. 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)

    本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...

  3. 2021-11-04太空大战项目制作

    太空大战项目制作 一.背景制作 1.创建一个Quad,更名为BG,并为其添加材质 2.设置旋转和放大参数 3.创建一个Quad,更名为BG2,并为其添加材质,作为BG的子对象,设置Y轴位置为-1 4. ...

  4. Unity3D 太空大战——整理

    Ok.now.begin! 今天同一整理学习了太空大战的开发.现在来做个总结: 1.首先是背景的生成和管理: 星空   直接建一张plane,再贴上星星的图片. 火星  mars.png   (生成一 ...

  5. 初学者Unity项目--太空大战

    太空大战算是比较经典的游戏了.这两天在跟着视频自学了一下.能做到的效果就是飞机发出子弹打爆陨石,如果被陨石碰到就死掉.简单的赤果果.界面如下: 现在做个总结:(模型声音之类的是导入的资源包.) 很明显 ...

  6. 太空大战--游戏ui和战斗管理

    太空大战–游戏UI和战斗管理 创建显示得分的UI界面 在Hierarchy视图中选择Create->UI->Canvas创建一个UI的根节点. 选中创建的Canvas,选择Create-& ...

  7. 中国电子学会青少年编程能力等级测试图形化四级编程题:太空大战

    「青少年编程竞赛交流群」已成立(适合6至18周岁的青少年),公众号后台回复[Scratch]或[Python],即可进入.如果加入了之前的社群不需要重复加入. 我们将有关编程题目的教学视频已经发布到抖 ...

  8. 【C语言游戏】太空大战 | SpaceWar(基于EasyX图形库,FPS优化,碰撞判断,drawAlpha绘制透明贴图,音乐播放,源码素材免费分享)

    1. 数据结构介绍 //飞船的数据结构(包括己方战机和敌机) struct aircraft { int x;//横坐标 int y;//纵坐标 int HP;//飞船血量 int spead;//飞 ...

  9. 视频教程-Unity经典案例再现《太空大战》-Unity3D

    Unity经典案例再现<太空大战> 专注于VR/游戏研发八年,精通各种常用语言,熟练使用Unity和UE4引擎开发. 张建飞 ¥12.00 立即订阅 扫码下载「CSDN程序员学院APP」, ...

最新文章

  1. 如何下载flash离线安装包
  2. 《Redis设计与实现》之第七章:压缩列表
  3. 1.1.2 标准化工作及相关组织
  4. 【Android】AsyncTask原理应用及源码关键部分解析
  5. 结构体指针struct stu *p;和结构体变量struct stu p;结构体为什么要用指针引用而不用变量引用
  6. lua元表(简单例子)
  7. C++面向对象笔记:构造、析构函数、成员函数
  8. HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容
  9. 约瑟芬公主把乔治放在了第三位,对吧
  10. Map集合转换成实体类对象,实体类对象转换为map集合,互转工具类
  11. 理解全概率公式与贝叶斯公式
  12. Flutter报错: type ‘double‘ is not a subtype of type ‘int?‘或type ‘int‘ is not a subtype of type ‘double
  13. XCTF-攻防世界-密码学crypto-新手练习区-writeup
  14. awl多进程SYN攻击
  15. css三实现ui,纯CSS实现常见的UI效果
  16. 有没有英语语音测试软件,没有雅思的高分女朋友虐你英语,就善用手机的app录音自测练习...
  17. python 对比两张图片是否相同
  18. 淘宝要社交:改变买家购买方式 取消商品排名(转载)
  19. matlab 判定空值NaN
  20. 养生之道——》痘痘:部位原因

热门文章

  1. 阿里软件测试工程师手把手教学—如何快速定位bug 编写测试用例?
  2. 无线自组网技术衍生:MESH无线自组网系统
  3. qt之QCustomPlot与qchart初级应用-----绘制动态曲线
  4. 从小白开始学习Java 第一期
  5. Mac及Linux安装Autodock及ADT
  6. 通通WPF随笔(4)——通通手写输入法(基于Tablet pc实现)
  7. 2022年了你必须要学会搭建微前端项目及部署方式
  8. 【C语言】空战游戏(二维数组)
  9. 移动云计算:问题与挑战
  10. 浅析移动云计算服务端技术