zoukankan      html  css  js  c++  java
  • Unity3D_(游戏)双人3D坦克_简易版

    双人3D坦克实现

      

      player1: WSAD控制上下左右   空格键发射炮弹

      player2: IKJL可控制上下左右  B键发射炮弹 

      每个坦克只有100hp,子弹击中1次扣30hp,hp时时显示在坦克上

        当一辆坦克hp低于0时,游戏结束

      Main Camera聚焦两辆坦克中心点   

      游戏项目已托管到github上(里面有个32bit可执行文件)  传送门

        (官方demo 素材包有点大。。)

    游戏界面

         (觉得子弹射程短,可以适当提高游戏子弹速度)

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.SceneManagement;
    
    public class FollowCamera : MonoBehaviour {
    
        public GameObject tank1;
        public GameObject tank2;
        public float size= 0.58f;
    
        Vector3 p;
    
        // Use this for initialization
        void Start () {
            Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
            p = target - transform.position;
         }
        
        // Update is called once per frame
        void Update () {
            if (tank2 != null&&tank1!=null)
            {
                //计算出两个坦克之间的距离
                transform.position = (tank1.transform.position + tank2.transform.position) / 2 - p;
    
                //找到两个坦克的中点
                //让摄像机对准中心点
                //根据两点之间的距离,调整摄像机的尺寸
                float distance = Vector3.Distance(tank1.transform.position, tank2.transform.position);
                GetComponent<Camera>().orthographicSize = distance * size + 2f;
            }
    
            if(tank2 == null || tank1 == null)
            {
                SceneManager.LoadScene("SampleScene");
            }
    
        }
    }
    FollowCamera.cs 初始化游戏脚本
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class TankHealth : MonoBehaviour {
    
        public int hp = 100;
        public GameObject ex;
        public Slider slider;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
        public void TakeDamage()
        {
            hp -= 30;
            if (hp < 0)
            {
                Destroy(gameObject);
                GameObject go = Instantiate(ex, transform.position, transform.rotation);
            }
            slider.value = hp;
    
        }
    
    }
    TankHealth.cs 坦克血量脚本
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class DestroyForTime : MonoBehaviour {
    
        // Use this for initialization
        void Start () {
            Destroy(gameObject,2);
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    }
    DestroyForTime.cs 粒子动画销毁脚本
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shell : MonoBehaviour {
    
        public GameObject ex;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
        private void OnCollisionEnter(Collision collision)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex,transform.position,transform.rotation);
            //判断是否打中坦克
            if(collision.gameObject.tag == "Tank")
            {
                collision.gameObject.GetComponent<TankHealth>().TakeDamage();
            }
            //扣除坦克的血量
    
        }
    }
    Shell.cs 判断是否打中坦克脚本
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shoot : MonoBehaviour {
    
        public GameObject shell;
        Transform pos;
    
        public KeyCode key = KeyCode.Space;
    
        public float speed = 180;
    
        // Use this for initialization
        void Start () {
            //找到子对象
            pos = transform.Find("FirstPosition");
        }
        
        // Update is called once per frame
        void Update () {
            //按下一个按键
            if (Input.GetKeyDown(key))
            {
                GameObject go = Instantiate(shell,pos.position,pos.rotation);
                go.GetComponent<Rigidbody>().velocity = go.transform.forward * speed;
                //go.GetComponent<Rigidbody>().velocity = Vector3.forward * speed;
            }
        }
    }
    Shoot.cs 子弹轨迹脚本
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Movement : MonoBehaviour {
    
        public float speed = 10;
        public float angularSpeed = 5;
    
        public string player = "1";
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            //获得玩家的键盘输入
            float v = Input.GetAxis("Vertical"+player);
            float h = Input.GetAxis("Horizontal"+ player);
           
            //让坦克前后移动
            GetComponent<Rigidbody>().velocity = transform.forward * v * speed;
            GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;
    
        }
    }
    Movement.cs 控制坦克方向脚本

    实现过程

      

    创建场景

      导入坦克资源场景

      

      

        Lightmapping光照贴图技术是一种增强静态场景光照效果的技术,其优点是可以通过较少的性能消耗使静态场景看上去更加真实,丰富,更加具有立体感;缺点是不能用来实时地处理动态光照。当游戏场景包含了大量的多边形时,实时光源和阴影对游戏的性能的影响会很大。这时使用Lightmapping技术,将光线效果预渲染成贴图使用到多边形上模拟光影效果。
    光照贴图

      加载光照贴图有时候会造成场景卡顿

        Auto Generate  :设置成不自动生成

        Generate Lighting  :生成一次场景光照

    坦克的前后移动

      添加坦克预设体进入游戏场景,DustTrail粒子特效预设体放到坦克上

      (GameObject ->Align  With View 将Game视图对准当前Scene视图)

      给坦克添加碰撞器和刚体

      (碰撞器慢慢移,拖动数值调整到刚好包围完坦克)

      添加移动坦克脚本

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Movement : MonoBehaviour {
    
        public float speed = 5;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
    
            //获得玩家的键盘输入
            float v = Input.GetAxis("Vertical");
            //让坦克前后移动
            GetComponent<Rigidbody>().velocity = transform.forward * v * speed;
    
    
        }
    }
    Movement.cs

      设置坦克移动速度

      public float speed = 5;

      获得玩家的键盘输入

    float v = Input.GetAxis("Vertical");

      让坦克前后移动

    GetComponent<Rigidbody>().velocity = transform.forward * v * speed;

      (将相机放到坦克里面,实现相机和坦克一起移动)

    坦克的旋转

      查看Unity输入按键值

      水平移动:Vertical

      左右移动:Horizontal

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Movement : MonoBehaviour {
    
        public float speed = 10;
        public float angularSpeed = 5;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            //获得玩家的键盘输入
            float v = Input.GetAxis("Vertical");
            float h = Input.GetAxis("Horizontal");
           
            //让坦克前后移动
            GetComponent<Rigidbody>().velocity = transform.forward * v * speed;
            GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;
    
        }
    }
    Movement.cs

      设置坦克移动转动角速度

      public float angularSpeed = 5;

      获得玩家的键盘输入

     float h = Input.GetAxis("Horizontal");

      让坦克前后移动

    GetComponent<Rigidbody>().angularVelocity = transform.up * h * angularSpeed;

      为实现双人坦克效果,提高按键灵活性,在InputManager管理器中添加两个Axes

      修改Axes值Horizontal1、Horizontal2、Vertical1、Vertical2

        

    我把玩家二上下左右WSAD按键修改为IKJL,实现双人笑游戏效果

      默认角色是1号玩家

           public string player = "1";
    
            //获得玩家的键盘输入
            float v = Input.GetAxis("Vertical"+player);
            float h = Input.GetAxis("Horizontal"+ player);
               

      新建双人坦克修改Player值

    坦克子弹

      给子弹添加刚体和碰撞器

      (将子弹设置为预设体,保存到Gary文件夹中)

      给坦克添加一个空物体,每次坦克都是从这个点动态生成子弹发射出去的

      添加Shoot脚本,挂载到坦克物体上

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shoot : MonoBehaviour {
    
        public GameObject shell;
        Transform pos;
    
        // Use this for initialization
        void Start () {
            //找到子对象
            pos = transform.Find("FirstPosition");
        }
        
        // Update is called once per frame
        void Update () {
            //按下一个按键
            if (Input.GetKeyDown(KeyCode.Space))
            {
                //发射子弹 实例化
                Instantiate(shell,pos.position,pos.rotation);
            }
         
    
        }
    }
    Shoot.cs

      引用子弹实例化

     public GameObject shell;

      找到子弹发射的位置

     pos = transform.Find("FirstPosition");

      按下一个按键,,将子弹实例化

            if (Input.GetKeyDown(KeyCode.Space))
            {
                Instantiate(shell,pos.position,pos.rotation);
            }

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shoot : MonoBehaviour {
    
        public GameObject shell;
        Transform pos;
    
        public KeyCode key = KeyCode.Space;
    
        // Use this for initialization
        void Start () {
            //找到子对象
            pos = transform.Find("FirstPosition");
        }
        
        // Update is called once per frame
        void Update () {
            //按下一个按键
            if (Input.GetKeyDown(key))
            {
                Instantiate(shell,pos.position,pos.rotation);
            }
    
        }
    }
    Shoot.cs

      在外添加一个key,按任意键可以射出子弹

         public KeyCode key = KeyCode.Space;
    
            //按下一个按键
            if (Input.GetKeyDown(key))
            {
                Instantiate(shell,pos.position,pos.rotation);
            }    

      定义子弹发射速度

     public float speed = 180;

      按下一个按键,子弹发射出去

            if (Input.GetKeyDown(key))
            {
                GameObject go = Instantiate(shell,pos.position,pos.rotation);
                go.GetComponent<Rigidbody>().velocity = go.transform.forward * speed;
                go.GetComponent<Rigidbody>().velocity = Vector3.forward * speed;
            }

    子弹爆炸动画

      添加脚本shell,挂载到子弹物体对象上

        private void OnCollisionEnter(Collision collision)
        {
            Destroy(gameObject);
        }

      当子弹碰到刚体时销毁自己

      添加子弹碰到物体触发爆炸效果

      引用粒子特效

    public GameObject ex;
       private void OnCollisionEnter(Collision collision)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex,transform.position,transform.rotation);
        }

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class Shell : MonoBehaviour {
    
        public GameObject ex;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
        private void OnCollisionEnter(Collision collision)
        {
            Destroy(gameObject);
            GameObject go = Instantiate(ex,transform.position,transform.rotation);
        }
    }
    Shell.cs

    子弹血量的减少

      给坦克添加标签

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class TankHealth : MonoBehaviour {
    
        public int hp = 100;
        public GameObject ex;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
         public void TakeDamage()
        {
            hp -= 30;
            if (hp < 0)
            {
                Destroy(gameObject);
                GameObject go = Instantiate(ex, transform.position, transform.rotation);
            }
        }
    
    }
    View Code

      初始化血量hp=100

     public int hp = 100;

      设置坦克爆炸粒子效果

      public GameObject ex;

      当血量低于0时,坦克销毁,爆炸粒子效果出现

        public void TakeDamage()
        {
            hp -= 30;
            if (hp < 0)
            {
                Destroy(gameObject);
                GameObject go = Instantiate(ex, transform.position, transform.rotation);
            }
        }

    相机跟随

      将照相机改为正交

      在摄像机中添加并挂载FollowCameral脚本

      两个坦克的引用

        public GameObject tank1;
        public GameObject tank2;

      两个坦克之间的中点

        Vector3 p;
    
       Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
        p = target - transform.position;

      计算出两个坦克之间的距离

     transform .position= (tank1.transform.position + tank2.transform.position) / 2 - p;

      找到两个坦克的中点并让摄像机对准中心点,根据两点之间的距离,调整摄像机的尺寸

            float distance = Vector3.Distance(tank1.transform.position,tank2.transform.position);
            GetComponent<Camera>().orthographicSize = distance * size+ 2f;

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class FollowCamera : MonoBehaviour {
    
        public GameObject tank1;
        public GameObject tank2;
        public float size= 0.58f;
    
        Vector3 p;
    
        // Use this for initialization
        void Start () {
            Vector3 target=(tank1.transform.position + tank2.transform.position) / 2;
            p = target - transform.position;
         }
        
        // Update is called once per frame
        void Update () {
            //计算出两个坦克之间的距离
            transform .position= (tank1.transform.position + tank2.transform.position) / 2 - p;
    
            //找到两个坦克的中点
            //让摄像机对准中心点
            //根据两点之间的距离,调整摄像机的尺寸
            float distance = Vector3.Distance(tank1.transform.position,tank2.transform.position);
            GetComponent<Camera>().orthographicSize = distance * size+ 2f;
    
    
        }
    }
    FollowCamera.cs

    添加音效

      在Main Camera上绑定Audio Source音乐播放器

    血条

      创建一个Slider,把Canvas移动到坦克上

      设置Slider控件的 PosX=0 PosX=0 PosZ=0

      参数下如下配置

     

      设置完成后效果如下

      设置成垂直

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class TankHealth : MonoBehaviour {
    
        public int hp = 100;
        public GameObject ex;
        public Slider slider;
    
        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    
        public void TakeDamage()
        {
            hp -= 30;
            if (hp < 0)
            {
                Destroy(gameObject);
                GameObject go = Instantiate(ex, transform.position, transform.rotation);
            }
            slider.value = hp;
    
        }
    
    }
    TankHealth.cs

      添加Slider控件

     public Slider slider;

      坦克攻击时,时时刷新slider.value值

        public void TakeDamage()
        {
            hp -= 30;
            if (hp < 0)
            {
                Destroy(gameObject);
                GameObject go = Instantiate(ex, transform.position, transform.rotation);
            }
            slider.value = hp;
    
        }

    完结!

    (如需转载学习,请标明出处)
  • 相关阅读:
    一、redis的简介与安装
    三、Mybatis全局配置文件说明
    第七章、本地方法栈
    第六章、本地方法接口
    二、MyBatis接口开发
    第五章、虚拟机栈
    一、Mybatis入门
    第八章、声明式事务管理
    第七章、JdbcTemplate
    第六章、以XML方式配置切面
  • 原文地址:https://www.cnblogs.com/1138720556Gary/p/9541955.html
Copyright © 2011-2022 走看看