franciscochonge 发表于 2022-5-23 07:19

【坦克大战3D版】制作一款小游戏真的很简单!

坦克大战

前言

坦克大战小游戏,想必只要是能刷到这篇博客的,无一例外都是玩过这款经典童年游戏的。记得小时候每到放学或者周六日,都会一起聚到有影碟机的小伙伴家里,然后打开“屁股超级大”的电视机和影碟机,将游戏碟放进去、手柄插上去。这个时候哪怕一天不吃饭也能在电视机前坐一天 。

尤其是坦克大战更是经典中的经典,小时候手残,最多打几关就打不过了。唉,真是又菜又爱玩 。正好昨天逛博客的时候,发现了一位叫明世隐的大佬用Java写了一个坦克大战,真是又让我们回忆起了童年的味道呀。然后我就想着用Unity来做一个坦克大战的升级版——“坦克大战3D”版
先来看一下效果图,场景之类的就忽略我的UI能力哈哈,以后可以找个好点的场景,或者自己搭个地形,再搞个好看的UI就好啦。害,就是玩~
简单游戏界面图



方案

感觉这个游戏做起来应该不难,正好拿来一起练练手嘿,做之前先理一下==思路==。

[*]首先,有一个主角坦克,那就是我们自己要控制的坦克啦~ 有什么功能呢?当然是移动、转弯、打炮弹啦。这个时候可以考虑一下,既然是号称”3D升级版”,那是不是应该显得特别一点呢!那好,我们待会可以考虑给他加上跳跃(虽然感觉跳跃没啥用…但是这就是我们主角应该跟小兵不一样的地方!哈哈哈哈嗝。当然我们还要有生命,加血条或者打一下就嗝屁都行,这个看心情
[*]其次要有敌方坦克,敌方坦克的话要在地图上随机生成,然后要给一个随机移动,还要有一个可以检测玩家的攻击范围,当然也要有生命值啦。还应该有炮弹,让我们的炮弹更霸气一点!地方的就弱一点哈哈~
[*]然后就是该有一个游戏场景啦,可以在场景中加一些障碍物,也可以简单一点制作,我这里分别使用了一个Unity官方的坦克大战地形和自己搭建的一个,这个看心情叭~
好了,坦克大战中该有的元素都差不多了,接下来就是要动手操作啦!
<hr/> Unity引擎视图操作

首先,我们需要搭建一个游戏场景,我们的坦克们才能激情的对打呀!
那么我们就来随便搭建一个简陋的游戏场景 边缘围墙就是我们的边界,我们的坦克们就只能在场景里面玩耍啦 或者直接找个场景先放上就好啦



<hr/>相机操作

我们只需要一个简单的跟随主角坦克移动的相机就好啦,想要更复杂的可以参考我之前写的几种相机跟随方法哦。在这里就不多做研究了,只要能看到我们的坦克大杀四方就好啦~Unity使用心得 | Unity中 多种相机视角跟随方式 (第一、三人称都有哦,快来看看叭)☆(ゝω)v
预制体操作

先添加我们的坦克预制体,主角坦克要给他加个Tag为Player,这样我们的坦克就有一个属于自己的标志了。然后加上碰撞体和刚体,用来模拟物理效果。
因为我想让我们的坦克炮筒可以按照我们的鼠标方向进行旋转,所以又给炮筒单独写了个脚本用于转向和开炮操作的,然后脚本挂到炮筒上就好啦~~
敌方坦克,也要加碰撞体和刚体,因为敌方坦克的攻击范围逻辑我是用检测器来做的,然后检测到玩家后就转向玩家,开始触发开炮!
然后就是我方炮弹和敌方炮弹的预制体啦,需要给炮弹加上自己的标签用来区分,我这里是给自己的炮弹加了bullet,再挂上我们之前做的脚本就好啦,然后想弄怎样的炮弹就看我们的心情啦哈哈,我这炮弹怎么样,看着就霸气!!
炮弹图


游戏演示图





我做了两种版本,一个是炮筒不动的,一种是炮筒跟随鼠标移动的。上面演示的是鼠标不跟随的,然后给大家演示一下这个鼠标跟随的效果 游戏演示图


由于录制画面的图片太大,过了5M就上传不了了,所以只能展示部分效果,想看的可以自己导入工程看哦 这个工程源码,和我已经打包出来的apk都有,想要玩玩的可以下载试试呀
<hr/>其实两种方式很好切换,只要把挂在炮筒上这个脚本的这行代码开启就可以跟随鼠标移动啦!


好了,简单说了一下在Unity引擎里操作,那接下来就是各部分代码的组成部分啦
<hr/>开发过程代码介绍

刚才说了一下玩家坦克需要有的操作。玩家坦克移动、转身等。那就用代码来实现一下吧,下面就是简单的代码逻辑:
//挂在我们的主角坦克身上的
public class playerTank : MonoBehaviour
{
   
    public float movespeed = 5f;
   
    public float turnspeed = 5f;
   
    public GameObject bulletPrefab;

    private float hor, ver;
    private Transform firePoint;
    private GameObject crtBlt;
    private Rigidbody rig;

    private void Awake()
    {
      firePoint = transform.Find("Buttom/Top/Gun/firePoint");//获取炮筒位置
      rig = GetComponent<Rigidbody>();//获取加速
    }
    void Update()
    {
      hor = Input.GetAxis("Horizontal");
      ver = Input.GetAxis("Vertical");
      //前后移动
      transform.position += ver* transform.forward * Time.deltaTime * movespeed;
       //左右转身
      transform.eulerAngles += hor* Vector3.up * turnspeed;
    }
}
因为我想要给我们的坦克的炮筒可以按照鼠标的方向进行单独旋转,所以就单独加了一个脚本,将开炮操作也加到炮筒上了,这个看自己心情,想怎么做就怎么做啦,就是玩儿!
//这是要挂在我方坦克炮筒上的代码
public class turnMouse : MonoBehaviour
{
   
    public GameObject bulletPrefab;
   
    public float continuousEmissionInterval = 0.1f;
    public float rotionspeed = 1f;

    private floattimer = 0f;
    private Ray ray;
    private RaycastHit hit;
    private Transform firePoint;
    private GameObject crtBlt;
    private void Awake()
    {
      firePoint = transform.Find("Top/Gun/firePoint");//获取炮筒位置
    }
    void Update()
    {
      //鼠标在屏幕的位置
      Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
      if (Physics.Raycast(ray,out hit))
      {
            Debug.DrawLine(Camera.main.transform.position,hit.point,Color.red);
      }
      Vector3 target = hit.point;//获取鼠标的位置
       // target.y = transform.position.y;//将鼠标Y轴目标传给玩家
      target.y = hit.point.y;
      transform.LookAt(target);//保证目标是鼠标的Y轴
      transform.eulerAngles += Vector3.up * rotionspeed;

      ContinuousEmission();//发射炮弹
    }
    //连发
    void ContinuousEmission()
    {
      if (Input.GetButton("Fire"))
      {
            timer += Time.deltaTime;//计时器计时
            if (timer > continuousEmissionInterval)
            {
                //生成炮弹
                crtBlt = Instantiate(bulletPrefab, firePoint.position,
                  Quaternion.identity);
                crtBlt.GetComponent<bullet>().dir = transform.forward;
                timer = 0;//计时器归零
            }
      }
    }
然后是挂在敌方坦克身上的脚本,让他们可以随机移动转向,发现我们之后还会自动攻击!可得小心点,别把我们心爱的小坦克给打炸了~~
//挂在敌方坦克身上的代码
public class enemyTanks : MonoBehaviour
{
   
    public GameObject bulletPrefab;
   
    public float moveSpeed = 1f;
   
    public float turnSpeed = 1f;
   
    public float attackDistance = 4;
   
    public float moveStence = 0.05f;

    private float times1 = 0f;//旋转计时器
    private float times2 = 0f;//开火计时器

    void tankmove()//坦克随机移动
    {
      transform.position += transform.forward * Time.deltaTime * moveSpeed;//坦克移动
      if (timeInterval==true)
      {
            times1 += Time.deltaTime;
         if(times1 > 3)
      {
            transform.localEulerAngles += Vector3.up * Random.Range(0,360)*turnSpeed;//坦克随机转弯
            times1 = 0;
      }
      }
    }
    void CreateBullt()//生成炮弹
    {
      crtBlt = Instantiate(bulletPrefab,transform.position,
            Quaternion.identity);
      crtBlt.GetComponent<bulletTwo>().dir1 = transform.forward;
      
    }
    private void OnTriggerStay(Collider other)//30米以内转向玩家
    {
      if (other.transform.tag ==("Player"))
      {   
            timeInterval = false;

            Vector3 target = player.position;
            target.y = transform.position.y;//将自身Y轴目标传给敌人
            transform.LookAt(target);//保证敌人目标是自己的Y轴
            transform.position += transform.forward * Time.deltaTime * moveStence;

            times2 += Time.deltaTime;
            if (times2 >= 3)
            {
                CreateBullt();//开炮
                times2 = 0;
            }
            float distance = Vector3.Distance(target,transform.position);
            if (distance<=attackDistance)
            {
                transform.position += transform.forward * moveStence*0;
            }
      }
    }
}
然后要有一个控制随机生成敌方坦克的,控制游戏的进程
//挂在场景的GameObject上
public class randomEnemy : MonoBehaviour
{
   
    public GameObject tanks;
    privatefloat times = 2f;
    private GameObject tank;
    private void produceTanks()
    {
      if (number <= 40)//控制坦克数量
      {
            times -= Time.deltaTime;//计算产生坦克时间
            if (times < 0)
            {
                int lenth = Random.Range(0, 100);
                int wide = Random.Range(0, 100);
                Vector3 enemyposition = new Vector3(lenth, 1, wide);//随机位置
                //产生坦克
                tank = Instantiate(tanks, enemyposition, Quaternion.identity);
                times = 1;//两秒产生一个坦克
      }   }   }
还有玩家坦克炮弹和敌方坦克炮弹的代码,因为我这里是想让双方炮弹产生一个不同的效果才用了两个脚本。只是一种处理方法,也可以精简成一个脚本,然后通过定义个标签或者枚举之类的来区分双方炮弹也可以,这里就仅供参考嘿嘿~_~
//挂在我方打出的炮弹身上的
public class bullet : MonoBehaviour
{
    // Start is called before the first frame update
   
    public float moveSpeed = 20;
    //方向向量
    public Vector3 dir;
    void Update()
    {
      //   transform.SetParent(null);
      //位移
      // transform.Translate(transform.forward * speed * Tie.deltaTime);
      transform.position += dir.normalized * Time.deltaTime * moveSpeed;
    }
}
挂在敌方打出的炮弹身上的
public class bulletTwo : MonoBehaviour
{
   
    public float moveSpeed = 5f;
    //方向向量
   publicVector3 dir1;
    void Start()
    {
      //延时销毁
      Destroy(this.gameObject, 3f);
    }
    void Update()
    {
      transform.position += dir1 * Time.deltaTime * moveSpeed;
    }
    private void OnCollisionEnter(Collision collision)
    {
      if (collision.transform.tag=="Player")
      {
            Destroy(collision.gameObject);
            Destroy(this.gameObject);
      }
    }
}
<hr/> 总结

好了,以上差不多就是一个小游戏坦克大战3D版的简单开发思路和过程啦,因为时间不够多,就简单做成这样了。 最好可以找个牛逼克拉斯的场景配上就更完美啦,也可以用Photon或者socket做成可以进房间联机的就更好了
如果大家有需要的也可以评论说一下,以后如果有时间我也可以做成个可以联网的,然后把场景弄个好看的,再加几个UI做个小成品一起玩。嘿嘿!就是玩儿~
如果有想做但是对Unity引擎不熟悉的小伙伴,那就需要在网上找一些介绍基础引擎使用的文章啦,后续有时间我也会更新一些自己使用Unity的经验和基础知识。嘿嘿~~还要更加努力呀   
本篇博客源码工程在这 想玩玩试试的可以下载看看呀~

页: [1]
查看完整版本: 【坦克大战3D版】制作一款小游戏真的很简单!