超详细 Unity 大作业之 坦克大战

这篇具有很好参考价值的文章主要介绍了超详细 Unity 大作业之 坦克大战。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本次大作业中,我选择的主题是制作一款简单的坦克大战小游戏,实现此项目借鉴并使用了BiliBili教程及资源和学姐的博,利用Unity自带的3D导航技术实现敌人坦克的自动导航。

演示视频:Unity大作业-坦克大战_演示

项目地址:坦克大战

参考视频:坦克大战教程

学姐博客:第15周-坦克


游戏设计

  • 坦克大战,必须包含3D导航技术(Enemy NPC使用unity的NavMeshAgent自动导航)
  • 坦克分为Player和Enemy(用两套逻辑脚本控制行为)。Player通过键盘输入控制移动和发射子弹,Enemy使用AI导航移动和利用协程发射子弹
  • 子弹伤害设置
  • 血条控制
  • 相机视野跟随
  • 美化(爆炸使用粒子特效,音效)

构建场景

首先准备游戏资源,在这

https://pan.baidu.com/s/1UXRHwSMr5DMDoPOCuv6beg
提取码:ksv7
unity坦克大战,unity,游戏引擎

具体实现

Player 坦克

Tank_Movement.cs (移动)

unity坦克大战,unity,游戏引擎

public class Tank_Movement : MonoBehaviour
{
    public float speed = 5;//坦克移动速度
    public float angularSpeed = 10;//坦克旋转速度
    public AudioClip idleAudio;//静止声音
    public AudioClip drivingAudio;//发动声音
    private new AudioSource audio;//声音组件
    private new Rigidbody rigidbody;
    // Start is called before the first frame update
    void Start()
    {
        rigidbody = this.GetComponent<Rigidbody>();//获得刚体组件
        audio = this.GetComponent<AudioSource>();//获得声音组件
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        float v = Input.GetAxis("Vertical");//对应键盘上下箭头,按下触发
        rigidbody.velocity = transform.forward*v*speed;//利用刚体加速度

        float h = Input.GetAxis("Horizontal");//对应键盘左右箭头,按下触发
        rigidbody.angularVelocity = transform.up*h*angularSpeed;

        if(Mathf.Abs(h) > 0.1||Mathf.Abs(v)>0.1){
            audio.clip = drivingAudio;
            if(audio.isPlaying==false)
                audio.Play();
        }
        else{
            audio.clip = idleAudio;
            if(audio.isPlaying==false)
                audio.Play();
        }
    }
}
Tank_Attack.cs (攻击)

unity坦克大战,unity,游戏引擎

小技巧:在坦克上添加emptygameobject 作为发射点(在坦克上绑定位置)

transform.Find() 在当前transform层级找子项

public class Tank_Attack : MonoBehaviour
{
    public GameObject shellPrefab;//子弹预制体
    public KeyCode fireKey = KeyCode.Space;//发射子弹键盘按键
    public float shellSpeed = 10;//子弹发射速度
    public AudioClip shotAudio;
    private Transform firePoint;
    // Start is called before the first frame update
    void Start()
    {
        firePoint = transform.Find("FirePoint");//找到发射点
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(fireKey)){//空格键按下后
            AudioSource.PlayClipAtPoint(shotAudio, transform.position);
            GameObject go = GameObject.Instantiate(shellPrefab, firePoint.position, firePoint.rotation);//在发射点位置实例化子弹
            go.GetComponent<Rigidbody>().velocity = go.transform.forward*shellSpeed;
            go.name = "Player";
        }
    }
}

Enemy 坦克

Npc_Movement.cs (使用NavMeshAgent 进行 AI 寻路)

先为gameobject添加NavMeshAgent component,再将参数调合适
unity坦克大战,unity,游戏引擎
unity坦克大战,unity,游戏引擎

3d导航很简单,只要将Enemy控件NavMeshAgent的目的地destination设置为Player position即可

 void Start()
    {
        sceneController = this.GetComponent<FirstController>();//获得
    }

    // Update is called once per frame
    void Update () {
        if(sceneController.getState()) {
            target = sceneController.getPlayerPosition();
            // 追踪玩家
            UnityEngine.AI.NavMeshAgent agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
            agent.destination = target;
        
        }
        else {
            // 游戏结束,停止寻路
            UnityEngine.AI.NavMeshAgent agent = GetComponent<UnityEngine.AI.NavMeshAgent> ();
            agent.velocity = Vector3.zero;
            agent.ResetPath();
        }
    }
Npc_Attack.cs (利用协程发射子弹)

IEnumerator 本质上 是C#的迭代器。

IEnumerator 可以理解为一个函数对象的容器(函数对象1 函数对象2 …),通过使用yield关键字,将yield关键字部分的函数代码抽出并生成一个函数,放到IEnumerator容器中。

yield return null;//暂停一帧
yield return new WaitForSeconds(1f);//1秒后继续执行

IEnumerator 可以依次执行容器中的函数,其实就是将函数进行分块处理

协程中Whille循环可以理解成一种状态,这里我们用协程+while循环来做状态机

场景一运行就在等待某个指令,一旦指令到达,就开始触发某个事(Player进入攻击范围发射子弹)

StartCoroutine(shoot()); 开启协程

void Start()
    {
        firePoint = transform.Find("FirePoint");//找到发射点
        sceneController = this.GetComponent<FirstController>();
        StartCoroutine(shoot());
    }

    // Update is called once per frame
    void Update()
    {
        if(sceneController.player){
            target = sceneController.getPlayerPosition();
        }
    }

    IEnumerator shoot(){ //协程实现npc坦克射击
        while(sceneController.player){
            if(Vector3.Distance(transform.position, target) < 10) {
            Debug.Log("fire");
            yield return new WaitForSeconds(1);
            GameObject go = GameObject.Instantiate(shellPrefab, firePoint.position, firePoint.rotation);//在发射点位置实例化子弹
            go.GetComponent<Rigidbody>().velocity = go.transform.forward*shellSpeed;
            AudioSource.PlayClipAtPoint(shotAudio, transform.position);
            go.name = "NPC";
            yield return 0;
            // yield return null;
            // yield return new WaitForSeconds(1f);//1秒后继续执行for循环
            }
            yield return 0;
        }
    }

上面代码实际就是在满足发射条件情况下将发射子弹分割为多个帧执行,避免在while里面符合发射条件的短时间内一直发射

Shell 子弹

Shell.cs

将Shell.cs代码add到Shell预制体上
unity坦克大战,unity,游戏引擎
unity坦克大战,unity,游戏引擎
Shell、Player、Enemy都有刚体和碰撞体,Shell开启碰撞检测

unity坦克大战,unity,游戏引擎

OnTriggerEnter(Collier collider) Shell碰撞到的物体作为参数传入

xx.SendMessage(“methodName”)调用此游戏对象中的每个 MonoBehaviour 上名为 methodName 的方法

小技巧:collider.tag区分碰撞体的类别。我们设置Player游戏对象的tag为Playear, Enemy游戏对象的tag为Enemyunity坦克大战,unity,游戏引擎

若是NPC发射的子弹碰撞到玩家,玩家减血;若是玩家发射的子弹碰撞到NPC,NPC减血

而NPC互相攻击不减血

    public void OnTriggerEnter( Collider collider){//子弹碰撞触发器
        AudioSource.PlayClipAtPoint(shellExplosionAudio, transform.position);
        GameObject.Instantiate(shellExplosionPrefab, transform.position, transform.rotation);//实例化爆炸效果
        GameObject.Destroy(this.gameObject);//删除子弹
        if(collider.tag == "Player"){//NPC发射子弹碰撞到玩家时
            collider.SendMessage("TankDamage");//给坦克发送消息 调用Tank里面函数
        }
        else if(this.name=="Player" && collider.tag=="Enemy"){//玩家发射子弹碰撞到NPC
            collider.SendMessage("TankDamage");
        }
    }

Slider 血条

unity坦克大战,unity,游戏引擎

血量显示

通过以上步骤和资源将血条作为子对象绑定到tank对象上
unity坦克大战,unity,游戏引擎

Tank_Health.cs (减少血量)

这个脚本挂在所有坦克上,hp表示当前血量,实现上一部分内容中子弹碰撞到坦克所调用的TankDamage()方法,将hp减小的同时要将绑定该脚本的游戏对象上的血条同步更新显示

bool TankDamage(){
        if(hp<=0)
            return false;
        hp-=Random.Range(10,20);
        hpSlider.value = (float)hp/hpTotal;//血条值范围0~1
        if(hp<=0){
            AudioSource.PlayClipAtPoint(tankExplosionAudio,transform.position);
            GameObject.Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation);
            GameObject.Destroy(this.gameObject);
            return true;
        }
        return false;
    }

MainCamera(主摄)

FollowTarget.cs (相机视野跟随)
	void Start () {
		offset = transform.position - player.transform.position;
	}
	
	// Update is called once per frame
	void LateUpdate () {
		if(player)
		transform.position = player.transform.position + offset;
	}

美化部分

粒子特效
子弹爆炸

Shell.cs的OnTriggerEnter()里

GameObject.Instantiate(shellExplosionPrefab, transform.position, transform.rotation);//实例化爆炸效果
坦克爆炸

Tank_Health的TankDamage()里

GameObject.Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation);
音效
背景音

Main场景创建空对象添加Audio Source组件

unity坦克大战,unity,游戏引擎

子弹爆炸音

Shell.cs的OnTriggerEnter()里

AudioSource.PlayClipAtPoint(shellExplosionAudio, transform.position);

unity坦克大战,unity,游戏引擎

同理实现了坦克爆炸音和启动音,静止音

不足

ransform.rotation);


#### 音效

##### 背景音

Main场景创建空对象添加Audio Source组件

[外链图片转存中...(img-fMNUApkb-1673111880522)]

##### 子弹爆炸音

Shell.cs的OnTriggerEnter()里

AudioSource.PlayClipAtPoint(shellExplosionAudio, transform.position);文章来源地址https://www.toymoban.com/news/detail-733967.html


[外链图片转存中...(img-V16MdQwe-1673111880523)]

同理实现了坦克爆炸音和启动音,静止音

## 不足

时间紧没完成工厂模式生成和管理Enemy.pre和Shell.pre,导演场景模式也未完成,还有就是UI和玩法比较单一

到了这里,关于超详细 Unity 大作业之 坦克大战的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java游戏开发 —— 坦克大战

    坦克大战也是小时一个比较经典的游戏了,我在网上也是参考了韩顺平老师写的坦克大战,并做了一下完善,编写出来作为儿时的回忆吧! 创建主窗口,加载菜单及游戏面板。 在游戏面板中初始化各种参数,并建立各种功能组件。 利用线程固定刷新游戏界面。 处理各种碰撞

    2024年02月06日
    浏览(55)
  • JAVA坦克大战游戏v3

    JAVA坦克大战游戏v3 素材 bomb_3.gif bomb_2.gif bomb_1.gif 项目结构 游戏演示 MyTankGame3.java Members.java

    2024年02月11日
    浏览(48)
  • Unity学习之坦克游戏制作(1)开始场景的制作

    相当于开始界面,想怎么创建就怎么创建 我最终模拟的效果 这部分不关键,关键的是创建可用来装载脚本的button 这部分感兴趣的可以去看我博客的GUI部分,但建议大家把学GUI的时间拿来学UGUI 导入预设体 Root 创建一格Label组件作为标题 这部分也可以自己创建 同时创建四个按

    2024年01月22日
    浏览(48)
  • final-期末大作业-制作AR射箭小游戏(Unity AR配置详细教程)

    链接: github仓库 bilibili视频 大作业要求: 制作一款特定技术应用小游戏,并提交技术报告。 内容(请参考以下技术主题,但不限于这些主题): 运用手机拍若干全景图,贴到天空盒或球型天空,做一个简单校园漫游功能。 粒子系统效果制作,必须带一个控制组件,控制粒子

    2024年02月06日
    浏览(49)
  • python小游戏毕设 坦克大战游戏设计与实现

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 《坦克大战》

    2024年02月05日
    浏览(62)
  • 毕业设计 python坦克大战小游戏

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取:

    2024年02月21日
    浏览(43)
  • python项目分享 - python坦克大战小游戏

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取:

    2024年02月03日
    浏览(43)
  • python毕设分享 python坦克大战小游戏

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取:

    2024年02月03日
    浏览(53)
  • python项目分享 - 坦克大战小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取:

    2024年02月01日
    浏览(50)
  • python项目分享 坦克大战小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 坦克大战小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取:

    2024年01月25日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包