花一天时间做一个高逼格打飞机游戏,过万字Unity完整教程!漂亮学妹看了直呼打飞机666!

Posted God Y.

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了花一天时间做一个高逼格打飞机游戏,过万字Unity完整教程!漂亮学妹看了直呼打飞机666!相关的知识,希望对你有一定的参考价值。

  • 📢博客主页:https://blog.csdn.net/zhangay1998
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 God Y.原创,首发于 csdn🙉
  • 📢未来很长,值得我们全力奔赴更美好美好的生活✨

🍌打飞机

  • ☀️阳光明媚,司机盎然,空气中充斥着荷尔蒙的气息,又到了万物开始交配的季节了~
  • 😇咦~ 搞错了!重来~
  • 🙉一日天气尚好 闲来无事,欲出门吟诗作赋, 偶遇一位漂亮学妹~
  • 👩学妹一脸天真,曰(yūe):“学长 geigei~,你打飞机厉害咩?”
  • 😅我略显尴尬,曰:“咳咳,还行吧…”
  • 👩学妹又曰:“人家也想学打飞机哎,要不然你教教人家嘛~”
  • 🤪我曰:“这个…是需要天分的!吾不知你天分如何,先来测测你可好?”
  • 👩学妹跃跃欲试,曰:“好嘛 geigei~ 尽管来!”
  • 🧐于是我曰:“打飞机三大要点是什么?请答!”
  • 👩学妹表情坚毅,曰:“首先要快,其次要准,最后要狠!”
  • 🥰我曰:“完美通过!那接下来我就教你怎样做一个打飞机的游戏,以及成为一名-打飞机高玩!”

在这里插入图片描述


📢正文

上文为雨后睡前小故事,下面步入正文

  • 前段时间看CSDN有个大佬用Java做了一个打飞机的游戏,看着他打飞机打的那么爽,我也想来做一个了。
  • 做游戏怎么能少了Unity这位专业人士呢~
  • 所以最近利用闲暇时间(摸鱼时间)也来搞一个打飞机的游戏

💫先来理一下思路

打飞机,顾名思义,我们要围绕飞机来展开思路

  1. 首先,要创建一个游戏场景,就是我们即将进行"打飞机"的场景!最好能让场景移动来体现真实感~
  2. 其次,要创建一个我们的主角飞机,当然要显得跟敌人飞机不一样啦。我们的飞机可以上下左右BABA移动,也可以发射炮弹来打飞机!自然也要有血量,不然无敌起来打飞机还有什么乐趣呢,就进不了贤者模式了!
  3. 然后再就是敌人啦,打飞机打飞机,没有飞机怎么打~,那就来加入敌方飞机,让他们随机加入战斗,再加上一些障碍物,让打飞机的场景更加惊心动魄!
  4. 再就是游戏对象的销毁,包括敌人被消灭,子弹销毁等等~
  5. 最后就是要有一个游戏控制器,来控制敌机的生成时间和数量,还有打飞机结束时的胜利和失败等游戏细节控制

好啦,一个简单的游戏思路就构思完成了,那么接下来就是按照这个思路来展开开发计划啦


🌟开始制作

这里我们导入一个Unity官方的飞机大战的资源包,就不用自己用一个简陋的三角裤来当飞机了,可以更高大上一点。
导入后如下图,然后就是按照我们提前想好的思路动手操作啦。
在这里插入图片描述

第一步:设置场景

我们导入资源包后第一步是配置游戏场景
Game视图点击下图所示地方可以配置游戏视图分辨率,就是我们玩游戏时候的游戏屏幕,将宽高比设置为600×900。 这里只是提供参考,一个竖版的游戏画面。
在这里插入图片描述
也打开Player Setting进行配置
Player Setting也以在Edit -> Project Settings -> Player中打开,也是将宽高比设置为600×900。两种方法都可以
在这里插入图片描述
设置完之后Game视图是这样的~,一个简单的游戏屏幕空间设置完成
在这里插入图片描述


第二步:配置我方飞机

在这个资源包中已经有飞机了,Assets/Module/Player
所以我们把这个飞机拖到Hierarchy窗口,然后改名为Player
在这里插入图片描述
给他加上刚体:Add Component -> Physics -> Rigibody
碰撞体:Add Component -> Physics -> Mesh Collider
加这两个组件是为了实现碰撞效果,所以有必要加上

把Player的组件属性设置好,我们不需要飞机有重力,因为这样会掉下去,所以把刚体(Rigibody)的UseGravity选项给关掉,这样就不使用重力效果了。

下图是飞机的Inspector的最终面板属性
在这里插入图片描述
然后资源包里面还有一个飞机尾部喷气的粒子特效,我们给它加到飞机尾部,直接将粒子特效的文件拖到飞机上就行。如下图(游戏背景在下一个步骤,这里录屏了就懒得换啦~):
在这里插入图片描述


第三步:设置场景里的相机和光照效果

相机处理

  • 我们要把相机放到一个合适的位置才能更好地体验游戏,光照是为了游戏效果更好
  • 直接上数据来设置一下——数据是死的,人是活的,具体怎样设置都行,这里只是提供一个参考数值~

设置相机属性值

  1. 重置相机的Transform
  2. Rotation的x设置为90
  3. Position的y设置为10,z设置为5
  4. Projections设置为orthographic(正交投影),因为相机俯视整个场景,不需要perspective(透视投影)
  5. Size设置为10
  6. Clear Flags设置为Solid Color
  7. Background设置为黑色

相机Inspector面板属性:
在这里插入图片描述
此时的Game视图如下,是不是黑乎乎的呢,因为还没有处理光照,下一步就是光照
在这里插入图片描述
光照处理

  • 光照的话主要是为了让场景里面看着更舒服,不那么违和,所以这里也设置一个参考值
  1. 将场景里的Directional Light改为MainLigjt
  2. 重置Main Light的属性
  3. 将Main Light的Rotation的x设置为20,y设置为-115

Main Light最终参数如下:
在这里插入图片描述
这样的话相机和光照就简单处理好了,此时的Game视图如下,是不是跟上面的比效果好点了呢~
在这里插入图片描述


第四步:更换游戏背景

此时的Game视图黑乎乎的,跟高逼格差十万八千里好吧,最起码游戏背景需要加上才行
步骤如下:

  • 新建一个Quad,重命名为Background01。方法:在Hierarchy中右键->3D Object->Quad
  • 将tile_nebula_green_dff拖拽到场景中的Background。路径:Assets\\Textures\\tile_nebula_green_dff
  • tile_nebula_green_dff是资源包中的一张图,可以用来做背景

直接来看Background的Inspector面板属性,照着这个属性设置就行,效果图如下:
在这里插入图片描述
复制一个背景,改名为Backgroun02,然后属性面板设置成这样
在这里插入图片描述

  • 然后给背景游戏对象加一个脚本,可以让背景动起来

  • 一般游戏应该都是让背景动起来,然后主角没动也显得动起来啦~

  • 通过判断Z轴参数来让两个背景板替换,形成无限循环的效果~

背景移动看效果(此时飞机应该还不会动,在下一步中,录屏啦就没换~):
在这里插入图片描述
上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BGController : MonoBehaviour
{
    private float MoveSpeed = 1.0f;//背景移动速度
    private void FixedUpdate()
    {
        transform.Translate(Vector3.down * Time.deltaTime * MoveSpeed);//移动
        if (transform.position.z <= -30)//如果z轴小于-30
        {
            transform.position = new Vector3(0, 0, 30);//循环位置
        }
    }
}

这样的话,一个简单的游戏背景就处理好了,接下来就是开始写代码让我们的飞机动起来啦!


第五步:飞机控制脚本的实现

  • 现在游戏场景设置完毕,就要来写代码操控飞机啦
  • 先让飞机动起来吧,新建一个脚本命名为PlayerController,通过按下键盘上的上下左右键通过Rigidbody控制飞机上下左右移动
  • 再加入一个speed参数作为velocity的系数,,可以在面板上调节飞机的飞行速度

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [Header("移动速度")]
    public float speed;
    private Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        rb.velocity = movement * speed;
    }
}

此时保存代码运行游戏是这样的:
在这里插入图片描述
但是此时有个问题就是,飞机操控没有边界,甚至跑出游戏场景外都有可能,那我们就用代码来控制一下
PlayerController脚本修改如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Boundary
{
    [Header("边界控制")]
    public float xMin, xMax, zMin, zMax;
}

public class PlayerControllder : MonoBehaviour
{
    [Header("移动速度")]
    public float Speed = 5f;
    public Boundary boundary;
    private Rigidbody rb;
  
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        rb.velocity = movement * Speed;

        //飞机边界设置
        rb.position = new Vector3(
            Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax),
            0.0f,
            Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax)
            );
    }
}

  • 代码中增加了一个Boundary类,其中有四个变量用于控制边界的四个顶点
  • 还在Boundary类上面加了一个 [System.Serializable] ,加它的目的是让Boundary类能够在Inspector面板上显示

Inspector面板属性设置按照下图所示就可以:
在这里插入图片描述
现在飞机可以在边界里自由移动,而且不用担心会跑出边界啦
但是移动的时候感觉很生硬,不够丝滑亮眼呀,这跟我们的高逼格好像又不沾边了…

那我们来给飞机移动的时候加上一个倾斜的效果试试看,说干就干,操作起来:

  • 想让飞机倾斜有很多种方法,那我们这里就控制欧拉角,让飞机左右移动的时候绕着Z轴旋转一个角度,就能达到我们想要的效果啦
  • 在代码中加一个float参数用于控制倾斜力度,然后在FixedUpdate中加入这行代码控制飞机的rotation
  public float tilt;
  
rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * -tilt);

Inspector中将tilt的值修改为4就可以了
在这里插入图片描述
来看一下加了倾斜后的效果图:
在这里插入图片描述
这样在左右移动的时候是不是就显得丝滑多啦,Nice!


第六步:飞机子弹控制

  • 现在我们的飞机只能移动,但是还不能发射炮弹呢,不能发射炮弹,还叫什么打飞机啊!
  • 那我们就来把炮弹加上,然后使用脚本控制发射炮弹炮弹的预制体在资源包中路径:Assets/Prefabs/Bolt
  • 给炮弹先加上一个简单的脚本,用于控制炮弹发射后可以向前出击!
    speed参数是炮弹的飞行速度,可以在面板上自定义修改,这样炮弹在生成之后就会向前发射飞行了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Mover : MonoBehaviour {
    [Header("炮弹移动速度")]
    public float speed;
    private Rigidbody rb;

	void Start () {
        rb = GetComponent<Rigidbody>();
        rb.velocity = transform.forward * speed;
	}
}

现在炮弹有了,我们给主角飞机Player创建一个子对象,用于控制炮弹发射时候的出生位置

简单来说就是,设置炮弹发射时候的位置,要位于player飞机前面一点。

就比如现实世界上飞机的炮筒,炮弹都是从炮筒发射出去的,总不能从飞机驾驶舱发出去吧~哈哈哈哈嗝

如下图设置,将炮弹发射点放在飞机靠前一部分就行了,这样显得不会太突兀~
在这里插入图片描述

  • 然后我们来修改PlayerController脚本,新增一个发射炮弹的功能
  • Instantiate()方法是Unity中生成预设体的方法,我们把炮弹作为预设体
  • 然后利用代码在点击鼠标左键的时候,执行生成炮弹的方法就可以达到我们想要的发射炮弹的方法了
  • Input.GetButton(“Fire”) 就是执行点击鼠标左键的时候调用,使用Input.GetMouseButton(0) 效果一样
  • 还增加1个private对象nextFire,用于计算炮弹连发时间间隔,一直 秒射 怎么行!加上个时间显得 更 持久~

上代码看一下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Boundary
{
    [Header("边界控制")]
    public float xMin, xMax, zMin, zMax;
}

public class PlayerControllder : MonoBehaviour
{
    [Header("炮弹预设体")]
    public GameObject bullet;
    [Header("移动速度")]
    public float Speed = 5f;
    public Boundary boundary;
    public float tilt=4f;
    public Transform shotSpawn;//炮弹发射点

    private GameObject bolt;
    private Rigidbody rb;
  
    private float fireRate=0.2f;//发射间隔
    private float nextFire;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    private void Update()
    {
       Fire(); 
    }
    public void Fire()
    {
        if (Input.GetButton("Fire1") && Time.time>nextFire)
        {
            nextFire = Time.time + fireRate;
            bolt = Instantiate(bullet,transform.position,Quaternion.identity);
        }
    }

    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis("Vertical");

        Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical);
        rb.velocity = movement * Speed;

        //飞机边界设置
        rb.position = new Vector3(
            Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax),
            0.0f,
            Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax)
            );
        //飞机侧身
        rb.rotation = Quaternion.Euler(0.0f, 0.0f, rb.velocity.x * -tilt);
    }
}

Inspector中指定脚本的public对象,将炮弹和发射点拖过去。方法有多种,这里只演示一种参考
在这里插入图片描述
这个时候我们运行游戏,就可以看到下图所示效果啦~
在这里插入图片描述


第七步:创建敌人

终于到这一步了,我们的主角飞机都可以自由移动巡逻发炮弹了,那怎么还没有飞机让我打呢,我的大枪都饥渴难耐了!

那我们现在就来加上可以让我们攻击的敌人~
因为资源包内容有限,所以我们这里就加入几种天外陨石来凑数!
操作起来~

创建陨石

陨石的资源路径:Assets/Prefabs/Asteroid 01
这里面的预制体是我添加好的,可以直接拿来用,简单说一下怎样配置的

这个敌人预制体上面都加了刚体(Rigidbody)和碰撞体(Capsule Collider)

  1. Asteroid -> Add Component -> Rigidbody,取消勾选Use Gravity,以防止陨石掉落地。Angular Drag设置为0,用于忽略空气阻力。
  2. Asteroid -> Add Component -> Capsule Collider,勾选上Is Trigger,Radius设置为0.45,Height设置为1.5

在这里插入图片描述
然后给陨石添加上一个可以随机自由翻转的脚本,让游戏加一些亮点。

Random.insideUnitSphere 用于返回一个随机的Vector3变量来让陨石达成随机翻转的效果!
上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RandomRotator : MonoBehaviour {
	public float tumble;
	private Rigidbody rb;

	void Start () {
        rb = GetComponent<Rigidbody>();
		rb.angularVelocity = Random.insideUnitSphere * tumble;
	}
}

效果图:
在这里插入图片描述
创建敌机

现在我们已经有了陨石了,那就再来加一个敌机。
考虑两个点:

  • 1.敌人会发射炮弹攻击我们
  • 2.敌人会随机改变游走方向

这样我们的游戏更真实,而且难度会变高
操作起来~

资源包中有敌人素材Assets/Prefabs/Enemy Ship

这个跟陨石一样,参数也差不多,也是我事先做好的预制体
也是都加了刚体(Rigidbody)和碰撞体(Capsule Collider),不多赘述了,直接看参数
在这里插入图片描述
这样的话敌人就算有了,但是我们要给他加上发射炮弹随机移动的脚本
上代码:
发射炮弹的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WeaponController : MonoBehaviour
{
	public GameObject shot;
	public Transform shotSpawn;
	public float fireRate;
	public float delay;

	void Start()
	{
		InvokeRepeating("Fire", delay, fireRate);
	}

	void Fire()
	{
		Instantiate(shot, shotSpawn.position, shotSpawn.rotation);

		GetComponent<Audiosource>().Play();
	}
}

控制敌人随机改变方向的脚本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EvasiveManeuver : MonoBehaviour
{
    public Boundary boundary;
    public float tilt;
    public float dodge;
    public float smoothing;
    public Vector2 startWait;
    public Vector2 maneuverTime;
    public Vector2 maneuverWait;

    private float currentSpeed;
    private float targetManeuver;
    
    private void Start()
    {
        currentSpeed = GetComponent<Rigidbody>().velocity.z;
        StartCoroutine(Evade());
    }

    IEnumerator Evade()
    {
        yield return new WaitForSeconds(Random.Range(startWait.x,startWait.y));
        while (true)
        {
            targetManeuver = Random.Range(1, dodge) * -Mathf.Sign(transform.position.x);
            yield return new WaitForSeconds(Random.Range(maneuverTime.x, maneuverTime.y));
            targetManeuver = 0;
            yield return new WaitForSeconds(Random.Range(maneuverTime.x,maneuverTime.y));  
        }
    }

    void FixedUpdate()
    {
        float newManeuver = Mathf.MoveTowards(GetComponent<Rigidbody>().velocity.x, targetManeuver, smoothing * Time.deltaTime);
        GetComponent<Rigidbody>().velocity = new Vector3(newManeuver, 0.0f, currentSpeed);
        GetComponent<Rigidbody>().position = new Vector3
        (
            Mathf.Clamp(GetComponent<Rigidbody>C系列Unity3D | 花一天时间做个经典小游戏Pacman

老Java程序员花一天时间写了个飞机大战,媳妇直呼打飞机高手

(转 )Android那些高逼格的写法InvocationHandler与代理模式

如何定义一个高逼格的原生JS插件

android:怎样用一天时间,写出“飞机大战”这种游戏!(无框架-SurfaceView绘制)

Java迷宫小游戏,老程序员花一天时间完成,你可以吗?