内容纲要

GIF效果展示

黑洞大作战详细思路插图黑洞大作战详细思路插图(1)

设计思路:

  1. 玩家的移动、吃物体和敌人、被敌人吃掉、用遥感移动、玩家升级变大
  2. 敌人的移动。被玩家吃掉、吃掉场景中的物体、敌人寻找可以吃掉的物体,在范围内敌人等级大于玩家时追击玩家
  3. 物体被吃掉掉落、物体过一段时间刷新、物体不能被玩家吃掉与玩家碰撞修改透明度
  4. UI,得分、时间、开场动画、结束动画、再来一局按钮
  5. 相机跟随玩家移动、玩家升级是拉远
  6. 得分的上升以及淡出

数据架构

  1. 单件类:存放两个数组一个是得分达到多少可以升级的用于判断的数组,另一个是玩家或者敌人变化的Scale值得数组
  2. 基类:
    • 等级
    • 速度
    • 缩放值
    • 得分
    • 玩家或者敌人派生类继承于基类
  3. 玩家派生类:
    • 调用单件类里的数组
    • 继承基类数据
    • 旋转值
    • 判断是否可以改变scale的bool值
    • 定义一个可以被吃物体的分数变量int值
    • 声音组件
    • 相机组件
    • 坐标组件
  4. 敌人派生类:
    • 继承基类数据
    • 调用单件类里的数组
    • 怪物坐标组件
    • 玩家坐标组件
    • OBJ坐标组件
    • 寻找的OBJ对象
    • 音效组件
    • 是否需要看到玩家转向的bool值、吃掉物体加分的量int值、scale发生改变bool值、平滑mathf需要的0参数值。

功能实现

  1. 玩家
    (1)碰撞吃掉OBJ或者怪物
    (2)在不能吃掉的OBJ发生碰撞使得OBJ变得透明
    (3)吃掉OBJ或者怪物得分,得分达到一定值时升级体型变大

  2. 敌人
    (1)找到玩家,判断玩家等级,高于自己躲避,低于自己追玩家。
    (2)视野内没有玩家是找可以吃掉的OBJ
    (3)碰撞吃掉OBJ,吃掉玩家游戏结束
    (4)和玩家一样得分到达一定值时升级体型变大

  3. 相机
    (1)相机随玩家变大缓慢拉远

  4. UI
    (1)游戏刚开始是缓慢淡出logo和游戏名字
    (2)游戏开始时启动游戏倒计时
    (3)根据不同模式,判断玩家是否复活,或者死亡结束本局游戏,显示排行榜

  5. 对象池
    (1)用于生成敌人,敌人死亡时,重新生成

  6. OBJ
    (1)判断是否可以被敌人或者玩家吃掉,可以被吃掉掉落
    (2)过一段时间重新生成在初始位置

  7. 添加游戏中警车巡逻
    (1)警车巡逻按照路点移动,是游戏画面更加美观。

  8. TTUI制作UI框架

  9. 接入广告,实现看广告得到新皮肤

  10. 异步加载场景。玩家的数据读写,用于解锁新皮肤,记录等级

  11. 添加陷阱,白色黑洞,会根据时间不断变大,玩家或者敌人都会被其吃掉

难点解决

  1. 玩家碰撞到吃不掉的OBJ时,使得OBJ变得透明
    解决方法: 更换被碰撞物体的材质

  2. 通过什么方法判断玩家和敌人变大
    解决方法: 在GameMessage脚本下创建两个数组,一个数组用来判断玩家和敌人的得分,得分大于数组里的一个等级时可以升级。另一个数组用来存玩家和敌人Scale的大小用来升级后进行改变。

  3. 敌人寻找玩家和可以吃掉的OBJ
    解决方法:创建一个数组存下所有OBJ,找到所有OBJ,遍历所有OBJ求得距离敌人最近可以吃的OBJ,敌人向得到的OBJ移动吃掉它。
    判断敌人一定范围内是否可以寻找到玩家,先算得敌人和玩家距离,敌人和玩家距离大于敌人的判定范围并且敌人等级大于玩家,敌人就去追击玩家。

  4. 更换皮肤,实现皮肤解锁功能

  5. 排行榜以及TTUI制作使用

注意事项

  1. 被吃物体挂载的obj脚本要设置obj等级

  2. 要记得选择按钮触发事件(再玩一局)
    黑洞大作战详细思路插图(2)

  3. 分数数组要记得填写分数,以及scale数组
    黑洞大作战详细思路插图(3)

  4. 敌人以及玩家的碰撞体设置好,防止碰撞检测判断不出来

具体实现

  1. 场景搭建
    (1)在scene文件夹下打开game场景,将里面的模型导入到自己的场景
    (2)确定场景搭建完毕,确定都有碰撞体,物体有可能会掉落,可以给地面添加很大的一个碰撞体,防止物体掉落黑洞大作战详细思路插图(4)

  2. 创建文件夹导入插件
    (1)把物体下的脚本去除,在Assets下面创建两个文件夹Script、Scenes。Script用来存放脚本,Scenes用来存放场景。导入EasyTouch组件(Easy Touch 4 Touchscreen Virtual Controls v4.1.0)。

  3. 设置摇杆
    (1)找到EasyTouchBundle文件夹下EasyTouchControls下Examples打开一个场景挑选合适的摇杆。把摇杆导入至自己的场景。一定要到如在UI下面。按照下图进行设置,把摇杆的对象选为游戏玩家,Action设置为Translate,Affected axis设置好X,Z轴黑洞大作战详细思路插图(5)

  4. 调试玩家和敌人预制体
    (1)在Assets下Resources下找到玩家和敌人的预制体拖拽到自己场景中进行调试。把不需要的碰撞体删除掉。玩家和怪物各自拥有一个Sphere Collider碰撞体就可以。大小自己调试好。把玩家放在一个合适的位置。

  5. 数据架构脚本
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  6. 玩家脚本
    (1)玩家脚本需要包括碰撞检测(敌人或者OBJ),增加得分,升级变大。
    (2)首先玩家脚本继承基类MovableObject,设置玩家脚本自己需要的一些数据。
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  7. 敌人脚本
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  8. OBJ脚本
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  9. 摄像机脚本
    (1)相机更随玩家移动,玩家升级拉远摄像机
    (2)创建设置相机数据
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  10. 玩家加分淡入淡出效果
    (1)创建设置基本数据

        private float speed = 1f;//淡出的速度
        public float time;
        // Start is called before the first frame update
        void Start()
        {
            time = 15;
        }

    (2)淡入淡出函数(通过时间一定时间后分数淡出,并且分数有一个上升的过程,需要在循环下执行)
    原理生成一个数字,由玩家脚本得分了生成数字(数字作为预制体),该数字绑定这个脚本,时间一到数字和脚本都删除。

      void Update()
        {
                WriteScore();
                time -= 0.1f;
                if (time >= 0)
                {
                    InstScore();
                }
                if (time < 0)
                {
                    time = 10f;
                Destroy(gameObject);//用完就删
                }
    }
    
        public void WriteScore()
        {
            this.gameObject.GetComponent<Text>().text =$"+{Player.instance.score}";//重写分数
        }
        public void InstScore()//淡出加分
        {
            float t = 1 / speed * Time.deltaTime;
            Color c = this.gameObject.GetComponent<Text>().color;
            c.a = Mathf.Lerp(c.a, 0, t);
            this.gameObject.GetComponent<Text>().color= c;//借书还书
            transform.position=transform.position +new Vector3(0,0.2f,0);
        }
  11. UI脚本
    (1)创建设置UI基本数据

        public RectTransform LOGO;//游戏初始背景图片
        public Transform uitransform;//ui坐标
        public static UI instance;//单利
        public GameObject ScoreText;//分数显示
        public GameObject GameOverScore;//游戏结束预制体
        public GameObject gameoverpanel;//游戏结束panel
        public bool IsGameOver = false;      //判断游戏是否结束了
        public Text AddScores;//加分的预制体text
        public Text TimeText;//时间显示
        private float totaltime=150f;   //游戏时间
        private float intervalTime = 1f;//每秒减去时间
         private void Awake()
        {
            instance = this;
        }
        private void Start()
        {
            StartCoroutine(Showlogo());
            uitransform = this.transform;
            TimeText.text = string.Format("{0:D2}:{1:D2}", (int)totaltime / 60, (int)totaltime % 60);//计时器
            StartCoroutine(CountDown());
        }

    (2)淡出背景图(一定时间消失,隐藏)

     IEnumerator Showlogo()//淡出背景图片
        {
            var cg = LOGO.Find("logo"). GetComponent<CanvasGroup>();
            while (cg.alpha < 0.95f)
            {
                //一直往不透明(1,0)插值
                cg.alpha = Mathf.Lerp(cg.alpha, 1, Time.deltaTime);
                yield return null;
            }
            yield return new WaitForSeconds(0.5f);//等待0.5秒
            cg.alpha = 1;
            LOGO.gameObject.SetActive(false);//隐藏
        }

    (3)倒计时的计时器(游戏时间)

     private IEnumerator CountDown()//倒计时
        {
            while (totaltime > 0)
            {
                yield return new WaitForSeconds(1);
                totaltime--;
                TimeText.text = string.Format("{0:D2}:{1:D2}", (int)totaltime / 60, (int)totaltime % 60);//重写时间
            }
        }

    (4)判断游戏是否结束,玩家吃东西得分是玩家脚本的CanchangeScores为true,生成得分text(淡出效果,上一个脚本有解释)。设置好位置把CanchangeScores改为false。

    private void Update()
        {
            if (totaltime <= 0)
            {
                IsGameOver = true;
            }
            if (IsGameOver == true)//游戏结束
            {
               GameOverScore.GetComponent<Text>().text =ScoreText.GetComponent<Text>().text;
                gameoverpanel.SetActive(true);
                //显示结束游戏
    
            }
            if (Player.instance.CanchangeScores == true)//玩家得分了玩家上方生成得分的text
            {
                var ui= Instantiate(AddScores).transform;
                ui.transform.SetParent(this.transform, false);
                ui.transform.localPosition = new Vector3(35, 0, 0);
                Player.instance.CanchangeScores = false;
            }
        }

    (5)设置在玩一局的按钮触发事件(按钮点击触发,重新加载场景)

     public void btnRestart()//重新加载场景
        {
            SceneManager.LoadScene(SceneManager.GetActiveScene().name);
        }

    黑洞大作战详细思路插图(6)

  12. 警车巡逻
    (1)创建警车预制体,在已有的模型中用Ctrl+D复制几个警车预制体
    (2)把警车预制体放在起始点,创建几个空节点将警车放在空节点下以便转向使用。
    (3)给空节点添加BoxCollider和Rigidbody组件。并且把Rigidbody组件里的Use Gravity勾选去掉,不使用重力。把Is Kinematic勾选上,不受重力影响。
    (4)在Script文件夹下创建一个叫MoveCar的脚本。
    (5)打开脚本,编辑脚本。脚本包括:车子向路点移动,车子向下一个点转向,碰到敌人或者玩家等于大于自己时掉落销毁。
    (6)

    public Transform[] WayPoints;//创建路点数组
    private float MoveSpeed = 10f;//设置车子移动速度
    // 当前人物需要移动的方向向量
    //Vector3 direction;
    // 下一个路点的索引
    public int nextIndex;//用于表示数组下一个点数值
    void Start ()
    {
        nextIndex = 0;
    }
    void Update ()
    {
        // 通过向量减法,算出朝向下一个路点的方向向量
        //向下一点POS移动
         transform.localPosition = Vector3.MoveTowards(transform.localPosition, WayPoints[nextIndex].localPosition, MoveSpeed * Time.deltaTime);
      Vector3 pos=new Vector3(WayPoints[nextIndex].transform.position.x,this.transform.position.y,WayPoints[nextIndex].transform.position.z);
             //向下一个点
             transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(pos - transform.position), 5 * Time.deltaTime);
    }
    
    void OnTriggerEnter (Collider other)//发生碰撞
    {
    if(other.tag=="Move"){//碰撞到POS点转向下一点移动
        Debug.Log (nextIndex);
        nextIndex++;
    }
     if (other.tag == "Player")//判断是否碰到玩家或者敌人下面的得分碰撞体
        {
                Player pl = other.gameObject.GetComponent<Player>();//找到玩家
                if(3<=pl.lvl)//判断等级
                {
                  Destroy(gameObject,2f);
                }
        }
        if (other.tag == "enemy")
        {
            Enemy EM = other.gameObject.GetComponent<Enemy>();//找到敌人
            if (3 <= EM.lvl)
            {
               Destroy(gameObject,2f);
            }
        }
        // 这里我使用了4个路点,会循环,所以每次到最后一个点就会回到起点
        // 大家可以根据自己的需求更改代码
        if (nextIndex >= 4) { 
            nextIndex = 0; 
        }
    }
  13. 白色陷阱黑洞制作
    (1)拷贝一个玩家或敌人的模型,把模型的颜色修改为白色,创建脚本Trap挂在陷阱的预制体上
    (2)白色黑洞要实现自己移动,经过一段时间变大,再经过一段时间消失
    (3)白色黑洞不会迟吃掉OBJ但会吃掉敌人和玩家。
    (4)脚本如下

    void Update()
    {
        time -= Time.deltaTime;
        StartCoroutine(Addlevel());
       StartCoroutine(RandomCoordinate());
    }
    IEnumerator Addlevel()//升级携程
    {
        if (time<=0)//判断条件得分大于需要得分的数组里的得分时升级
        {
            if (lvl < 5)
            {
            lvl += 1;
            CanChangeScale = true;//修改scale的判断bool值 
             a = Random.Range(0, 4);
            time = 10f;
            }
            if (lvl == 5)
            {
                Destroy(gameObject, 7f);
            }
        }
    
        Largen();
        yield return new WaitForSeconds(1);
    }
    IEnumerator RandomCoordinate()//随机方向移动
    {
        if (time >= 0)
        {
            if (a == 0)
            {
                target.position += new Vector3(0.1f, 0, 0);
            }
            if (a == 1)
            {
                target.position += new Vector3(0, 0, 0.1f);
            }
            if (a == 2)
            {
                target.position += new Vector3(-0.1f, 0, 0);
            }
            if (a == 3)
            {
                target.position += new Vector3(0, 0, -0.1f);
            }
        }
    
        yield break;
        // 等待时间重新随机位置
    }
        public   void scope()
        {
        if (target.position.x < -50)
        {
            a = 0;
        }
        if (target.position.x > 70)
        {
            a = 2;
        }
        if (target.position.z < -60)
        {
            a = 1;
        }
        if (target.position.z> 40)
        {
            a = 3;
        }
    }
        public void Largen()//修改大小
    {
        if (CanChangeScale == true)
        {
            if (lvl <= 5)
            {
            OBJLocalScale = Mathf.SmoothDamp(OBJLocalScale, GameMgr.instance.ScaleNum[lvl - 1], ref veclityScale, 0.6f);//+++++平缓修改scale
            trap.localScale = new Vector3(OBJLocalScale, OBJLocalScale, OBJLocalScale);//+++++
            if (Mathf.Abs(OBJLocalScale - GameMgr.instance.ScaleNum[lvl - 1]) < 0.01f)//计算scale和对应等级的scale值
                CanChangeScale = false;
            }
        }
    }
    private void OnTriggerEnter(Collider other)//碰撞游戏边界修改移动方向
    {
        if(other.tag== "scencecollider")
        {
            scope();
        }
    }

TTUI的接入制作

  1. 创建一个新场景叫做TTUI,在场景主界面可以导入一些场景,当做背景,用PS制作一个艺术字图片,贴在背景上面

  2. TopBar制作
    (1)主界面制作包括,左上角的经验条,记录玩家等级以及经验进度的Slider
    (2)右上角制作两个按钮分别是点击看广告的和调整震动的的按钮
    (3)右下角制作一个游戏开始按钮,点击会进行异步加载随机三个场景
    (4)添加两个按钮做成透明的样子,一上一下,用于做返回按钮
    (5)打开UITopBar脚本修改脚本
    【此处内容加入VIP后可见,咨询QQ:1517069595】
    (6)左上角的slider添加脚本实现异步加载
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  3. UIMain制作
    (1)UIMainPage实现点击出现换肤窗口以及点击出现选择模式窗口
    (2)脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  4. UINotice制作
    (1)弹窗可以更改是否震动
    (2)脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  5. UISkill2关卡模式选择
    (1)点击不同按钮实现关卡模式切换,添加按钮触发事件,点击按钮时按钮存下两个值,玩家是否可以复活,本关卡是否生成敌人。数据是通过配置配置出来的。再去读取配置的数据通过按钮事件把数据存下来。玩家以及敌人生成器在start运行时会读取数据判断是否可以复活,以及生成敌人
    (2)脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  6. MVC框架利用制作皮肤读取更换
    (1)导入MVC框架插件
    (2)创建两个脚本SkinPlayer,Datamanger利用MVC框架用来读写数据
    (3)Datamanger脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

  7. UISkillPage制作(接上面的MVC框架皮肤读取切换)
    (1)制作弹窗的皮肤
    (2)创建一个skinplayer读取皮肤需要从skinplayer的脚本进行读取
    (3)第一个和第二个皮肤在刚开始时可以切换,第三个皮肤要达到等级5自动解锁,第四个皮肤需要看广告后解锁
    (4)脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

    接广告

  8. 在Unity里面按Ctrl+0,把ADS打开,进行到网页设置界面

  9. 点击左边的Projects选择要添加广告的项目
    3.选择左边的Monetization下面的Placements,记录下显示的ID号用于接广告用

  10. 脚本实现
    【此处内容加入VIP后可见,咨询QQ:1517069595】

1 对 “黑洞大作战详细思路”的想法;

  1. Pingback: buy viagra

发表评论