【Unity2D入门教程】简单制作战机弹幕射击游戏⑥最终回扩展其它范围的内容

article/2025/7/15 19:40:24

制作分数和生命的UI:

由于我们前面没有做类似的UI所以这里教大伙一下基本思路:

首先我们创建一个canvas用来创建两个Text用来显示分数和生命的UI

蓝色的是分数黄色的是生命

我们创建一个scoreplay的脚本挂载在text上

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreDisplay : MonoBehaviour
{Text scoreText;GameSeesion gameSession;private void Start(){scoreText = GetComponent<Text>();gameSession = FindObjectOfType<GameSeesion>();}private void Update(){scoreText.text = gameSession.GetScore().ToString();}
}

创建一个空对象gamesession还有一个同名脚本挂载在它上面:

接着我们改一下Player和Enemy的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour
{[Header("玩家移动")][SerializeField] float ySpeed = 10f;[SerializeField] float xSpeed = 10f;[SerializeField] float padding = 1f;[Header("Play Health")][SerializeField] int health = 500;[Header("ProjectTile")][SerializeField] GameObject laserPrefab;[SerializeField] float projectTileSpeed = 10f;[SerializeField] float projectTileFiringPeriod = 0.1f;//战机在屏幕能移动的坐标float xMin;float xMax;float yMin;float yMax;//协程的编程是指在不堵塞主线程的情况下执行某些特定的函数Coroutine fireCoroutine;[SerializeField] AudioClip deathSFX;[SerializeField] [Range(0, 1)] float deathSoundVolume = 0.75f;[SerializeField] AudioClip shootSFX;[SerializeField] [Range(0, 1)] float shootSoundVolume = 0.55f;void Start(){SetUpMoveBoundaries();}private void SetUpMoveBoundaries(){Camera gameCamera = Camera.main;//之前的视频说过,Camera.main.ViewportToWorldPoint()是将摄像机视角的坐标转化为世界坐标然后padding是防止战机出屏幕边缘xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;}void Update(){Move();Fire();}private void Move(){//Input Manager上两个监控键盘上WSAD按键而生成-1到1值的var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * ySpeed;var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * xSpeed;// Debug.Log(deltaX);//限制移动范围var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);transform.position = new Vector2(newXPos,newYPos);}private void Fire(){if (Input.GetButtonDown("Fire1")){fireCoroutine =  StartCoroutine(FireContinuously());}if (Input.GetButtonUp("Fire1"))//这个Fire1也是Input Manager上的{StopCoroutine(fireCoroutine); //暂停某个协程// StopAllCoroutines();}}//协程函数是用关键字迭代器IEnumerator而且一定要用yield关键词返回IEnumerator FireContinuously(){while (true){GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.identity) as GameObject; //生成子弹laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, projectTileSpeed); //给子弹一个向上的力AudioSource.PlayClipAtPoint(shootSFX, Camera.main.transform.position, shootSoundVolume);yield return new WaitForSeconds(projectTileFiringPeriod); //下一颗子弹发生的间隔时间}}private void OnTriggerEnter2D(Collider2D other){DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();if (!damageDealer) { return; }ProcessHit(damageDealer);}private void ProcessHit(DamageDealer damageDealer){health -= damageDealer.GetDamage(); //减去收到的伤害damageDealer.Hit();if (health <= 0){Die();}}public int GetHealth(){return health;}private void Die(){Destroy(gameObject); //生命值为小于等于0就销毁AudioSource.PlayClipAtPoint(deathSFX, Camera.main.transform.position, deathSoundVolume);}
}

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour
{[Header("Enemy States")][SerializeField] float health = 100f;[SerializeField] int scoreValue = 150;[Header("Shooting")][SerializeField] float shotCounter;[SerializeField] float minTimeBetweenShots = 0.2f;[SerializeField] float maxTimeBetweenShot = 1.5f;[SerializeField] GameObject projecttile;[SerializeField] float projecttileSpeed = 10f;[Header("Sound Effects")][SerializeField] GameObject deathDFX;[SerializeField] AudioClip deathSFX;[SerializeField] [Range(0,1)]float deathSoundVolume = 0.75f;[SerializeField] AudioClip shootSFX;[SerializeField] [Range(0, 1)] float shootSoundVolume = 0.50f;void Start(){shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShot);}void Update(){CountDownAndShoot();}private void CountDownAndShoot(){shotCounter -= Time.deltaTime; //计时器,用来当计时器小于等于0时重置发射时间并执行发射函数if(shotCounter <= 0){Fire();shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShot);}}private void Fire(){GameObject laser = Instantiate(projecttile, transform.position, Quaternion.identity) as GameObject;//生成子弹并给它一个向下的力,因为和主角方向反过来的laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, -projecttileSpeed);AudioSource.PlayClipAtPoint(shootSFX, Camera.main.transform.position, shootSoundVolume);}private void OnTriggerEnter2D(Collider2D other){DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();if (!damageDealer) { return; }ProcessHit(damageDealer); //同样也是伤害处理的函数}private void ProcessHit(DamageDealer damageDealer){        health -= damageDealer.GetDamage();damageDealer.Hit();if (health <= 0){Die();}}private void Die(){FindObjectOfType<GameSeesion>().AddToScore(scoreValue);Destroy(gameObject);GameObject explosion = Instantiate(deathDFX,transform.position,transform.rotation);Destroy(explosion, 1f);AudioSource.PlayClipAtPoint(deathSFX, Camera.main.transform.position,deathSoundVolume);}
}

其次显示生命值的脚本也要创建好

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreDisplay : MonoBehaviour
{Text scoreText;GameSeesion gameSession;private void Start(){scoreText = GetComponent<Text>();gameSession = FindObjectOfType<GameSeesion>();}private void Update(){scoreText.text = gameSession.GetScore().ToString();}
}

 


创建Start和Game Over场景

其实

其实我前面教的差不多了,这里就直接把预设体拖进来就好

 

这里的Score Canvas是只需要score即可不需要生命的text

别忘了挂载onclike()监听事件


 

 

设置连贯的背景音乐:

为了防止音乐在切换场景时重新播放,我们也要创建一个单例给它

先空对象Music Player然后创建同名脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class MusicPlayer : MonoBehaviour
{private void Awake(){SetUpSingleton();}private void SetUpSingleton(){if(FindObjectsOfType(GetType()).Length > 1){Destroy(gameObject);}else{DontDestroyOnLoad(gameObject);}}
}

别忘了让它一直循环。


 

生成游戏:

别忘了放到build setting上然后点击PlayerSetting改图标

 

 游戏画面如下:

 

 

 


http://chatgpt.dhexx.cn/article/3I7hHsDl.shtml

相关文章

【Unity2D入门教程】简单制作战机弹幕射击游戏③C#编写 子弹Laser脚本

学习目标&#xff1a; 今天教大伙怎么设置子弹Laser的组件以及编写关于它的脚本 学习组件&#xff1a; 老规矩还是添加一下它的组件用capusle collider2D刚好它还是个圆柱体&#xff0c;别忘了勾选它的isTrigger Rigibody2D的Body Type调成是让它不受重力以及物理碰撞影响&a…

【Unity2D入门教程】简单制作战机弹幕射击游戏⑦番外篇扩展一个大型敌人

布置场景&#xff1a; 我们先按CrtlD复制一个之前创建好的Enemy Prefab&#xff0c;然后更改它的Sprite&#xff0c;我们拖一张素材的图片进来并改变它的Pixel Per Unit让它大其它敌机一倍 由于体型变大了之前的Coliider就不适用了我们要重新删掉之前的再创建一个新的 同样它的…

【Unity2D入门教程】简单制作战机弹幕射击游戏④C#编写 敌人按指定路径以及敌人生成点脚本

前言&#xff1a; 我们前面忘记设置的当敌机和子弹碰到特定的位置&#xff08;指屏幕外的&#xff09;就会自动销毁 挂载的脚本Sherred如下 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Shredder : MonoBehaviour {private…

【Unity2D入门教程】简单制作战机弹幕射击游戏⑤C#编写 背景滚动移动以及增加粒子特效

学习目标&#xff1a; 上期结束后我们游戏的主体就已经差不多了&#xff0c;剩下的就要给游戏的真实质感以及可玩性上下大点功夫了&#xff0c;今天我们就从背景滚动移动以及增加粒子特效上出发。 背景滚动制作&#xff1a; 为了让游戏更具真实性的就是让玩家从视觉上感受飞机…

【Unity2D入门教程】简单制作战机弹幕射击游戏② C#编写 Player和Enemy脚本

学习目标&#xff1a; 上期的水平大伙看到我已经写好了Enemy和Player的脚本了&#xff0c;现在就把脚本教给大伙&#xff0c;话不多说搞的不丑 学习内容&#xff1a; 首先是Player的脚本&#xff08;之前没发现CSDN有这个代码段的&#xff0c;我的我的&#xff09; using Sy…

【Unity2D入门教程】简单制作战机弹幕射击游戏① 导入素材

学习目标&#xff1a; 今天我们制作一款类似银河战机的游戏导入素材并给它设置一下背景&#xff0c;把素材做成预设体等等 首先先上网找到我们需要的素材 Unity Asset Store - The Best Assets for Game MakingDiscover the best assets for game making. Choose from our mas…

弹幕射击游戏中旋转矩形碰撞检测的算法描述

分离轴法是根据两个多边形的几何中心在任意矢量方向的法线上的投影存在交叉的条件来做出的方法[32]。换而言之&#xff0c;如果可以找出这样一个方向&#xff0c;将两个多边形投影在此方向的法线上的投影不交叉&#xff0c;则说明碰撞未发生&#xff0c;如图5-3所示。 图中A、B…

Cocos2d-x 简单弹幕射击游戏

开发环境 Win10, Cocos2d-x v3.16, Visual Studio 2017, Visual Studio Code 项目阐述 这个游戏是一个小型的弹幕游戏。玩家将控制pipi美&#xff0c;在躲避pop子的子弹之余&#xff0c;射杀pop子。名字打算叫“pop子的深邃黑暗幻想”。 游戏的设计主要借鉴了东方系列的弹幕游…

程序员职业规划和学习规划

程序员职业规划路线 技术体系 阿里程序员等级 学习规划

程序员职业发展规划

程序员职业生涯发展到一定的程度都会面临着职业发展方向选择的问题&#xff0c;随着年龄的增长&#xff0c;面对日新月异的代码&#xff0c;感到力不从心&#xff0c;更年轻的程序员层出不穷&#xff0c;这些都是促使程序员向另一个方向进行转型&#xff0c;那么&#xff0c;程…

程序员10年职业规划

从事Dotnet程序开发工作近10年了&#xff0c;从开始的月薪3k的小程序员菜鸟&#xff0c;到现在年薪60w的项目总经理&#xff0c;从战战兢兢的去各个公司应聘&#xff0c;到现在开始面试那些战战兢兢的小程序员&#xff0c;回想起这近十年来的经验&#xff0c;看着还是朝气蓬勃的…

女生做软件测试的职业规划,来说说女程序员的职业规划要怎么做

如果你是一名女程序员&#xff0c;你一定会为如何规划自己的职业生涯而感到苦恼。本期乔布 女程序员的职业规划 要怎么做。 关键词&#xff1a; 女程序员的职业规划 总体来说&#xff0c;女程序员的职业规划路线主要有四种&#xff1a;技术线路&#xff1b;业务路线&#xff1b…

女程序员的职业规划

女程序员的职业规划 引子 很多姐妹发微博评论留言给我&#xff0c;说希望我写一篇关于女程序员职业规划的文章。很惭愧&#xff0c;我自己的职业规划都还没亲自验证完毕&#xff0c;coder之路还在继续&#xff0c;在此仅仅分享我的所闻、所见、所学、所思&#xff0c;有…

Android程序媛大厂拧螺丝,未来职业如何规划?

作者&#xff1a;程军 上周有一位朋友咨询我职业规划问题。 我先介绍一下背景&#xff0c;她工作 2 年&#xff0c;985 本科毕业&#xff0c;目前在一家互联网大厂任职 Android工程师。 她主要咨询了我 4 个困惑问题&#xff0c;比如大厂拧螺丝怎么破&#xff1f;全年 996 没…

女神节-女性程序员有哪些好的职业发展路线

1、前言 祝天下作所有的女生节日快乐&#xff0c;在今天这个日子里&#xff0c;多陪陪自己的爱人、母亲&#xff0c;有时候不一定要礼物&#xff0c;真诚的对待和陪伴就是对她最好的爱。 最近为公司招聘测试岗位&#xff0c;岗位需求最好是女生&#xff0c;因为领导觉得在测…

一名女程序员的职业规划

前言&#xff1a; 在IT这个行业做了有几年了&#xff0c;身边的一些朋友有一部分已经转行了&#xff0c;也有部分正在为转行打基础做准备。所以我最近也在考虑这个问题&#xff0c;是应该继续做技术开发还是转产品之类的&#xff0c;还是直接转行做其他的职业。写下这篇博文&a…

c语言之运算符号

c语言的运算符有很多&#xff0c;希望做这份总结能够充分的利用这些运算符&#xff0c;编写出自己想要达到的效果 -----------------------------这是虚线还是实线&#xff0c;傻傻的分不清楚--------------------------------- 算数操作符 ###逻辑操作符 ###按位操作符 …

c语言运算符大全极其意义,C语言运算符大全

.. ;. C语言运算符大全 C语言的内部运算符很丰富&#xff0c;运算符是告诉编译程序执行特定算术或逻辑操作的符号。C语言有三大运算符&#xff1a;算术、关系与逻辑、位操作。另外&#xff0c;C还有一些特殊的运算符&#xff0c;用于完成一些特殊的任务。 2.6.1算术运算符 表2-…

单片机C语言基础运算符号

C语言中的运算符号分为10类&#xff1a;算术运算符、关系运算符、逻辑运算符、位操作运算符、赋值运算符、条件运算符、逗号运算符、指针运算符、求字节数运算符和特殊运算符。 重点讲讲位操作运算符&#xff0c;因为相信其他大家也很容易掌握。 位操作运算符 C语言中六种位运…