U3D小项目参考

U3D项目参考

++U3D小案例简述

++++这里是立钻哥哥汇总的几个U3D小案例,通过案例学习U3D的基本编程和技巧。

++++小案例会不断更新补充,通过学习掌握U3D的编程和思想。

++小案例目录:

++++小案例001、贪吃蛇Demo

++++小案例002、飞机大战Demo

++++小案例003MVC框架(提升等级案例)

++++小案例004、简单背包案例

++++小案例005、塔防Demo

++++小案例006、秘密行动Demo

++++小案例007A_Star

++++小案例008、血条LiftBar跟随

++++小案例009、见缝插针StickPin

++++小案例010UnityNetDemo

++++小案例011SocketFileRecv

++++小案例012、切水果CutFruitDemo

++++小案例013、吃鸡_友军方位UV

++++小案例014、数据库背包SqliteEZ_Bag

++++小案例015Json数据存储

++++小案例016、关卡系统LevelSystem

++++超级Demo:斗地主


#小案例001、贪吃蛇demo

++小案例001:贪吃蛇demo

++++Cube_Snake_Body.prefab

++++Cube_Snake_Food.prefab

++++Scene02Snake.unity

++++SnakeMoveScript.cs



###SnakeMoveScript.cs

C:\000-ylzServ_U3D_Pro\小案例001\Assets\DemoSnake\SnakeMoveScript.cs

++SnakeMoveScript.cs

 

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Linq;

using UnityEngine.SceneManagement;  //引入场景控制器

 

public  class SnakeMoveScript :  MonoBehaviour{

    /*

 蛇头移动:

    #1、蛇头移动(默认方向朝上,wsad控制移动)

    #2、生成食物(随机生成)

    #3、吃到食物后生成蛇身

    #4、游戏结束

    */

 

    //1、蛇头移动(默认方向朝上,wsad控制移动)

    Vector2  dirV2Move  = Vector2.up; //默认向上移动

    public float speedMoveRate= 5f;  //速度

    public GameObject  snakeBody;  //身体

    public GameObject  snakeFood; //食物

 

    //创建集合存放身体(蛇身)

    List<Transform> bodyList = new List<Transform>();

 

    bool  isCreate  =  false;  //控制是否创建身体

 

    //Use this for initialization

    void Start(){

        for(int   i =0; i <5; i++){

            Invoke(“CreatFood”,1.0f);  //延迟1秒,调用Creat

        }

 

        //在游戏开始1.5秒调用Move方法,然后每隔0.2秒再重复调用

        InvokeRepeating(“SnakeMove”,1.5f, 0.2f);  //每几秒重复调用这个函数

    }

 

    //Update is called once per frame

    void Update(){

        dirV2Move = GetMoveDir(); //获取控制方向

    }

 

    //触发检测

    void OnTriggerEnter(Collider other){

        if(other.gameObject.CompareTag(“SnakeFood”)){

            //如果碰撞到的是食物

            Destroy(other.gameObject); //销毁食物

            isCreate = true;

 

            Invoke(“CreatFood”,0.3f); //0.3秒之后创建食物

 

        }else if(other.gameObject.CompareTag(“SnakeBody”)){

            //碰到自己

            Debug.Log(“yanlzPrint:碰到自己身体了,游戏结束!);

            //todo优化碰到自己身体处理事件

 

        }else{

            Debug.Log(“yanlzPrint:碰到墙了,游戏重新开始!);

            SceneManager.LoadScene(“Scene02Snake”); //重新加载场景(新一局)

        }

    }

 

    //自定义函数

 

    //获取方向控制

    //1、蛇头移动(默认方向朝上,wsad控制移动)

    Vector2 GetMoveDir(){

        if(Input.GetKeyDown(KeyCode.W)){

            dirV2Move = Vector2.up;

        }else if(Input.GetKeyDown(KeyCode.S)){

            dirV2Move = Vector2.down;

        }else if(Input.GetKeyDown(KeyCode.A)){

            dirV2Move = Vector2.left;

        }else if(Input.GetKeyDown(KeyCode.D)){

            dirV2Move = Vector2.right;

        }

 

         return dirV2Move;

    }

 

    //生成食物

    void CreatFood(){

        Vector3  foodPosV3 new Vector3(Random.Range(-14,14),Random.Range(-14,14),0);

        Instantiate(snakeFood,foodPosV3,Quaternion.identity);

    }

 

    //移动方法

    void SnakeMove(){

        Vector3  curPos=   transform.position;  //移动之前,首先记录蛇头位置

 

        //创建蛇身

         if(isCreate == true){

             //创建身体

            Vector3 createBodyPosV3  = curPos; //在蛇头位置创建

            GameObject createBodyObj;

            createBodyObj = Instantiate(snakeBody,createBodyPosV3,Quaternion.identity);

            Color colorRandom  = new Color(Random.value,Random.value,Random.value);

            createBodyObj.GetComponent<MeshRenderer>().material.color  =  colorRandom;

 

              bodyList.Insert(0,createBodyObj.transform); //将身体插入到集合当中

              isCreate = false;  //将创建标志置为false

 

         }else if(bodyList.Count>0){

                //身体个数大于0

                //蛇身最后位置       //当前蛇头位置

               bodyList.Last().position = curPos; //更新蛇身位置

 

                //list里面元素进行交换位置,最后一个元素添加到最前面

               bodyList.Insert(0, bodyList.Last());

               bodyList.RemoveAt(bodyList.Count -1); //移除最后一个元素(因为其已经被加入到第一个位置)

          }

 

          transform.Translate(dirV2Move);  //改变当前蛇头位置

     }

}




#小案例002、耳轮跳(NG进行中)

++小案例002、耳轮跳demo

++++HudText.cs

++++BallFallScript.cs

++++CreateGap.cs

++++CreateRing.cs

++++CreateTrap.cs

++++GameMgr.cs

++++RingInfo.cs

++++RotatePillar.cs

++++SectorInfor.cs




###HudText.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\HudText.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public  class  HudText:MonoBehaviour{

    private void Start(){

        GameObject.Destroy(gameObject,1f);

    }

 

    //下落

    private  void  Update(){

        transform.position  -= Vector3.up*Time.deltaTime* 0.5f;

        GetComponent<CanvasGroup>().alpha  -= Time.deltaTime;

    }

 

    //设置值

    public void SetText(string s){

        transform.GetComponentInChildren<Text>().text=s;

    }

}


###BallFallScript.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\BallFallScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  BallFallScript:MonoBehaviour{

    float  g = -9.8f;

    float v = 0;

    float timer = 0;

 

    //1m的间距最大速度达到4.4m/s,这里考虑小球和平板的高度,取3.5f,也就是说最大速度为3.5f

    float  maxV = 3.5f;

 

    public int  power =0;    //小球势能

    public int powerToggle =3;    //达到层数,可以获得击碎能力

 

    private  void  Update(){

        Fall();

    }

 

    private  void Fall(){

        v = v + g *Time.delatTime;

        v = Mathf.Clamp(v, -maxV, maxV);

        transform.position += transform.up*Time.deltaTime*v;

    }

 

    private  void  LateUpdate(){

        float  y = Camera.main.WorldToScreenPoint(transform.position).y;

        if(y /Screen.height<0.7f){

            Camera.main.transform.SetParent(transform);

        }else{

            Camera.main.transform.SetParent(null);

        }

    }

 

    //碰撞结算

    private  void  OnCollisionEnter(Collision collision){

        v =maxV;

        Camera.main.transform.SetParent(null);

 

        SectorInfo si =collision.collider.GetComponent<SectorInfo>();

        if(power>=powerToggle){

            si.transform.parent.GetComponent<RingInfo>().Explosion();

        }else if(si.IsTrap&&si.transform.parent.GetComponent<RingInfo>().isBreaken == false){

            GameObject.FindObjectOfType<GameMgr>().GameOver();

        }

 

        power = 0;

    }

}


###CreateGap.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\CreateGap.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public  class  CreateGap:MonoBehaviour{

    public int minGapGroup=1;

    public int  maxGapGroup=3;

    public int  minGap=2;

    public int  maxGap=4;

 

    MeshCollider[]  sectors;

 

    private  void  Start(){

        sectors = GetComponentsInChildren<MeshCollider>()

 

        int group  = Random.Range(minGapGroup, maxGapGroup+1);

        for(int i =0; i<group; i++){

            int pos  = Random.Range(0,secotrs.Length);

            int gaps  = Random.Range(minGap,maxGap+1);

            for(int  j=0;j <gaps; j++){

               sectors[(pos+j) %sectors.Length].gameObject.SetActive(false);

            }

        }

    }

}


###CreateRing.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\CreateRing.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  CreateRing:MonoBehaviour{

    public  GameObject  ringPre;

 

    private  void  Start(){

        for(int  i = 0; i <100;i++){

            GameObject ring  = GameObject.Instantiate(ringPre,new Vector3(0, -50+i *1f),Quaternion.identity);

            ring.GetComponent<RingInfo>().index = i;

            ring.transform.SetParent(transform);

        }

    }

}


###CreateTrap.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\CreateTrap.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public  class  CreateTrap:MonoBehaviour{

    public int  minTrapGroup = 1;

    public int  maxTrapGroup =3;

    public int  minTrap = 2;

    public int  maxTrap = 4;

 

    MeshCollider[]  sectors;

 

    private  void Start(){

        sectors = GetComponentsInChildren<MeshCollider>();

 

        int group = Random.Range(minTrapGroup,maxTrapGroup+1);

        for(int  i = 0; i<group;i++){

            int pos = Random.Range(0, sectors.Length);

            int gaps = Random.Range(minTrap,maxTrap+1);

            for(int j=0; j<gaps; j++){

               int  index = (pos+ j) %sectors.Length;

               if(sectors[index].gameObject.activeSelf&&transform.GetComponent<RingInfo>().index<95){

                   sectors[index].GetComponent<MeshRenderer>.material.color = Color.red;

                   sectors[index].GetComponent<SectorInfo>.IsTrap=true;

                }

            }

        }

    }

}


###GameMgr.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\GameMgr.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.SceneManagement;

 

public class GameMgr:MonoBehaviour{

    //设置分数

    public Text  scoreText;

    public Text  levelText;

    public Button  restartBtn;

 

    public int score=0;

    public  bool  gameOver=false;

 

    priavate  void  Awake(){

        Time.timeScale=0;

        Screen.SetResolution(750,1334,false);

    }

 

    private void  Start(){

        restartBtn.onClick.AddListener(GameStart);

        restartBtn.gameObject.SetActive(false);

    }

 

    public void GameStart(){

        SceneManger.LoadScene(“Demo002_HelixJump_Lovezuanzuan”);

    }

 

    public void GameOver(){

        gameOver = true;

        Time.timeScale = 0;

        restartBtn.gameObject.SetActive(true);

    }

 

    private  void  Update(){

        if(Input.GetMouseButtonDown(0) && gameOver ==false){

            Time.timeScale = 1;

        }

    }

 

    public void AddScore(int  s, RingInfoinfo){

        score += s;

        HudText hud = ((GameObject)GameObject.Instantiate(Resources.Load(“HudText”))).transform.GetComponent<HudText>();

        hud.SetText(“+” + s);

 

        scoreText.text = score.ToString();

        levelText.text = info.index.ToString();

    }

}


###RingInfo.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\RingInfo.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//立钻哥哥:环信息

public  class RingInfo:MonoBehaviour{

    public int  index;    //层数

    public bool  isBreaken=false;    //是否击毁

    GameObject  ball;

 

    private  void  Start(){

        ball = GameObject.Find(“Ball”);

    }

 

    private  void Update(){

        if(ball == null){

            return;

        }

 

        if(ball.transform.position.y < transform.position.y - 0.1f && !isBreaken){

            isBreaken = true;

    

            //提高小球势能

            GameObject.Find(“Ball”).GetComponent<BallFallScript>().power += 1;

            int power=GameObject.Find(“Ball”).GetComponent<BallFallScript>().power;

 

            //计算分数,与通过的势能相等

            GameObject.FindObjectOfType<GameMgr>().AddScore(power*4,this);

 

            Explosion();

        }

    }

 

    public void Explosion(){

        //打散散开

        for(int i=0; i <transform.childCount;  i++){

            if(transform.GetChild(i).gameObject.activeSelf == false){

               continue;

            }

 

            Rigidbody  rig;

            if((rig = transform.GetChild(i).gameObject.GetComponent<Rigidbody>()) == null){

               rig = transform.GetChild(i).gameObject.AddComponent<Rigidbody>();

            }

            rig.AddForce((transform.GetChild(i).forward+Vector3.up*Random.Range(0.3f,1)) * Random.Range(40,80));

            transform.GetChild(i).GetComponent<MeshCollider>().enabled = false;

        }

 

        StartCoroutine(ChangeAlpha());    //渐隐

        GameObject.Destroy(gameObject,3);    //3s后销毁

    }

 

    IEnumerator ChangeAlpha(){

        float alpha = 1;

    

        while(true){

            alpha -= Time.deltaTime;

            for(int  i =0; i < transform.childCounti++){

               if(transform.GetChild(i).gameObject.activeSelf == false){

                   continue;

                }

 

                Material  mat =transform.GetChild(i).GetComponent<MeshRenderer>.material;

                transform.GetChild(i).GetComponent<MeshRenderer>.material.color= new Color(mat.color.r,mat.color.g,mat.color.b,alpha)

            }

 

            yield return null;

        }

    }

}


###RotatePillar.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\RotatePillar.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  RotatePillar:MonoBehaviour{

    private void  Update(){

        if(Input.GetMouseButton(0)){

            float y =Input.GetAxis(“Mouse X”);

            transform.Rotate(Vector3.up,  -Time.deltaTime*180*y);

        }

    }

}


###SectorInfor.cs

D:\zz_DemoPro()-\小案例002、耳轮跳-HelixJump-\Assets\Project\Scripts\SectorInfo.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  SectorInfo:MonoBehaviour{

    public bool  IsTrap{    get;    set;    }

}




#小案例003MVC框架(提升等级案例)

++小案例003MVC框架(提升等级案例)

++++PlayerMsgController.cs

++++PlayerMsgView.cs

++++PlayerScript.cs



###PlayerMsgController.cs

C:\000-ylzServ_DemoPro\小案例003\Assets\PlayerMsgController.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//Controller层:

public  class  PlayerMsgController : MonoBehaviour{

    public  static  PlayerMsgController  controller;

    private int levelUpValue=20;

 

    void Awake(){

        controller = this;

    }

 

    void Start(){

        PlayerScript.GetMod().PlayerLevel = 1;

        PlayerScript.GetMod().PlayerExperience = 0;

        PlayerScript.GetMod().PlayerFullExperience = 100;

        PlayerScript.GetMod().GoldNum = 0;

    }

 

    //提升经验按钮点击事件

    public void OnExperienceUpButtonClick(){

        PlayerScript.GetMod().PlayerExperience += levelUpValue;

 

        if(PlayerScript.GetMod().PlayerExperience >= PlayerScript.GetMod().PlayerFullExperience){

            PlayerScript.GetMod().PlayerLevel +=1;

            PlayerScript.GetMod().PlayerFullExperience += 200*PlayerScript.GetMod().PlayerLevel;

            levelUpValue += 20;

        

            if(PlayerScript.GeMod().PlayerLevel % 3 == 0){

               PlayerScript.GetMod().GoldNum += 100*PlayerScript.GetMod().PlayerLevel;

            }

        }

    }

}


###PlayerMsgView.cs

C:\000-ylzServ_DemoPro\小案例003\Assets\PlayerMsgView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

//立钻哥哥:UI视图层

public  class PlayerMsgView :MonoBehaviour{

    //UI

    public  Text playerLevel;

    public  Text playerExperience;

    public  Text goldNum;

    public  Button  experienceUpButton;

 

    void Start(){

        //委托事件绑定

        PlayerScript.GetMod().OnLevelChange += SetLevel;

        PlayerScript.GetMod().OnExperienceChange += SetExperience;

        PlayerScript.GetMod().OnFullExperienceChange += SetFullExperience;

        PlayerScript.GetMod().OnGlodNumChange += SetGoldNum;

 

        //View绑定按钮控制功能

        //添加观察者:

        experienceUpButton.onClick.AddListener(

        PlayerMsgController.controller.OnExperienceUpButtonClick);

    }

 

    //修改UILevel

    public void SetLevel(int  level){

        playerLevel.text = level.ToString();

    }

 

    //修改UI经验值

    public void SetExperience(int  experience){

        //将字符串以/拆开

        string[]  str = playerExperience.text.Split(newchar[]{‘/’ });

    }

 

    public void SetFullExperience(int  fullExperience){

        string[]  str = playerExperience.text.Split(newchar []{ ‘/’ });

        playerExperience.text  = str[0] +“/” + fullExperience;

    }

 

    public void SetGoldNum(int  goldn){

        goldNum.text = goldn.ToString();

    }

 

}


###PlayerScript.cs

C:\000-ylzServ_DemoPro\小案例003\Assets\PlayerScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//模型委托(当用户信息发生变化时执行)

public  delegate void OnValueChange(int  val);

 

public  class  PlayerScript{

    private int playerLevel; //玩家等级

    private int  playerExperience;  //玩家经验

    private int playerFullExperience;  //玩家升级经验

    private int goldNum;  //金币数量

 

    //声明委托对象

    public OnValueChange OnLevelChange;  //当等级发生变化时,触发的事件

    public OnValueChange OnExperienceChange;  //当经验发生变化时,触发的事件

    public OnValueChange OnFullExperienceChange;  //当升级经验发生变化时

    public OnValueChange OnGoldNumChange; //当金币数量发生变化时

 

    private static  PlayerScript  mod; //单例

    public  static  PlayerScript GetMod(){

        if(mod == null){

            mod = new  PlayerScript();

        }

        return  mod;

    }

    private  PlayerScript(){

    }

 

    //玩家等级属性

    public int  PlayerLevel{

        get{

           return playerLevel;

        }

        set{

            playerLevel = value;

            if(OnLevelChange!= null){

               //如果委托对象不为空

               OnLevelChange(playerLevel);  //执行委托

            }

        }

    }

 

    //玩家经验属性

    public int  PlayerExperience{

        get{

            return playerExperience;

        }

       set{

            playerExperience = value;

            if(OnExperienceChange !=null){

                 OnExperienceChange(playerExperience);

            }

        }

    }

 

    //玩家升级经验属性

    public int  PlayerFullExperience{

        get{

            return playerFullExperience;

        }

        set{

            playerFullExperience = value;

            if(OnFullExperienceChange!= null){

               OnFullExperienceChange(playerFullExperience);

            }

        }

    }

 

    //金币数量属性

    public int  GoldNum{

        get{

            return goldNum;

        }

        set{

            goldNum = value;

            if(OnGoldNumChange != null){

               OnGoldNumChange(goldNum);

            }

        }

    }

}



#小案例004、简单背包案例

++小案例004、简单背包案例

++++Controller/

--PlayerBagController.cs

++++Model/

--PlayerModelScript.cs

--ToolModel.cs

++++View/

--BagView.cs

--GridView.cs

--HPView.cs

--PlayerBagView.cs

--PlayerInfoView.cs







##Controller/

++Controller/

++++PlayerBagController.cs

###PlayerBagController.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\Controller\PlayerBagController.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.EventSystems;

using System;

using System.Reflection;

using UnityEditor;

 

//实现赋值数据,展示数据,物品拖拽,交换等主要功能

//    赋值M -- V交互

public  class  PlayerBagController :MonoBehaviour,IMoveHandle{

    //引入背包视图,相当于将其下的所有子物体脚本都引入

    public BagView  bagView; //背包视图

 

    void Start(){

        MakeData();  //赋值数据

        ShowData(); //展示数据

    }

 

    //测试数据:

    PlayerModelScriptplayer;

    public  Sprite  s1;

    public  Sprite  s2;

    public  Sprite  s3;

    public  Sprite  s4;

    //public Sprite s5;

    //public Sprite s6;

 

    void MakeData(){

        player = new  PlayerModelScript(立钻哥哥,1000,200);

        ToolModel   t1new  ToolModel(道具1”,ToolType.HP,2000,s1);

        ToolModel   t2 = new ToolModel(道具2”,ToolType.HP,500,s2);

        ToolModel   t3new  ToolModel(道具3”,ToolType.ATK,300,s3);

        ToolModel   t4=  new  ToolModel(道具4”,ToolType.ATK,100,s4);

 

        //放入指定下标

        player.bagArray[0] = t1;

        player.bagArray[5] = t2;

        player.bagArray[16] = t3;

        player.bagArray[7] =t4;

    }

 

    void ShowData(){

        //背包

        //生成背包格子

        creatGrid(

            player.bagArray,

           bagView.playerBagView.gridGroupView.transform,

           “BagGrid”);

  

        //装备

        creatGrid(){

            player.gearArray,

            bagView.playerInfoView.gridGroupView.transform,

            “GearGrid”

        };

 

        //显示生命值

        bagView.playerInfoView.hpView.HPValue.text=player.HP.ToString();

    }

 

    //1、根据数组元素个数生成

    //2、父物体

    //3、格子tag

    void creatGrid(ToolModel[]  arr, Transform  t, string  gridTag){

        for(int i=0; i <arr.Length; i++){

            //生成格子

            GameObject objInstantiate<GameObject>(

               Resources.Load<GameObject>(“Perfabs/GridView”),

               Vector3.zero,

               Quaternion.identity

            );

 

            //参数赋值:

            obj.tag = gridTag; //tag值:格子tag赋值给生成的格子

            GridView  gv = obj.GetComponent<GridView>(); //获取脚本组件

            gv.index =i; //设置格子index

             //走过之一段代码之后controller就为格子的代理,那么其就要执行接口里边的方法

             gv.moveHandle = this; //设置代理

 

            //给图片赋值

             if(arr[i]  != null){

               gv.contentImage.gameObject.SetActive(true);  //激活image

               gv.contentImage.sprite = arr[i].toolSprite;

             }

 

             //添加到父物体

            obj.transform.SetParent(t);

        }

     }

 

    /*

 移动有四种情况:

    --1、背包--->背包

    --2、背包--->装备

    --3、装备--->装备

    --4、装备--->背包

    --5、有--->

    --6、丹药类型点击消失增加属性

    */

    //实现接口方法

    Transform  targetTransform; //目标位置

 

    public void BeginMove(GridView  grid, PointerEventData  pointData){

            if(grid.tag ==  “BagGrid”){

                //判空:如果背包数组没有东西那么不需要移动

               if(player.bagArray[grid.index] == null){

                   return;

                }

            }

 

          if(gird.tag == “GearGrid”){

             //判空:装备格子判断

            if(player.gearArray[gird.index] == null){

               return;

            }

        }

        #warning有数据

 

        //有数据:开始拖拽前记录信息不交换时候让其回到原来位置

         targetTransform = grid.contentImage.transform;

        gird.contentImage.raycastTarget = false; //关闭射线检测(检测后方物体)

        targetTransform.SetParent(targetTransform.root); //脱离父物体

    }

 

    public void Move(GridView  grid,  PointerEventData pointData){

            if(targetTransform == null){

               //如果目标为空,那么返回原来位置

               return;

             }

            targetTransform.position = Input.mousePosition;

    }

 

    //PointerEventData:系统方法

    public void EndMove(GridView  grid,  PointerEventData  pointData){

            if(targetTransform==null){

               return;

             }

 

            //pointData.pointerEnter:目标物体

             GameObject pointerEnter = pointData.pointerEnter; //鼠标松手后最后触碰的物体

 

            //从背包区开始拖拽

             if(grid.tag == “BagGrid”){

                 //到背包区

                if(pointerEnter.tag == “BagGrid”){

                    GridView  gv = pointerEnter.GetComponent<GridView>();

        

                      //判断格子中是否有物品

                     //gv:目标格子

                    if(player.bagArray[gv.index] == null){

                       ChangeUINullGrid(grid, gv);  //grid:当前格子

                    }else{

                       ChangeUIFullGrid(grid, gv); //UI

                    }

 

                  //变数据

                ToolModel tm = player.bagArray[gv.index];

                player.bagArray[gv.index] = player.bagArray[gird.index];

                player.bagArray[grid.index] = tm;

             }

 

            //到装备区

            if(pointerEnter.tag == “GearGrid”){

                //判断拖拽的是否是装备

                 if(player.bagArray[gird.index].type == ToolType.ATK){

                   GridView  gv = pointerEnter.GetComponent<GridView>();//获取脚本组件

        

                    //判断是否有数据

                   if(player.gearArray[gv.index] == null){

                       ChangeUINullGrid(gird,gv); //

                     }else{

                       ChangeUIFullGrid(grid,gv); //

                    }

 

                     //数据交换

                     ToolModel tm = player.bagArray[gird.index];

                      player.bagArray[gird.index] = player.gearArray[gv.index];

                      player.gearArray[gv.index] = tm;

                }

            }

        }

 

        //从装备区拖拽

        if(grid.tag == “GearGrid”){

            //到装备区

            if(pointerEnter.tag == “GearGrid”){

                GridView  gvpointerEnter.GetComponent<GridView>();

               if(player.gearArray[gv.index] == null){

                   ChangeUINullGrid(grid,gv); //

                }else{

                   ChangeUIFullGrid(grid,gv);  //不空

                }

 

                //交换数据

               ToolModel tm = player.gearArray[gv.index];

               player.gearArray[gv.index] = player.gearArray[grid.index];

               player.gearArray[grid.index] = tm;

             }

 

            //到背包

            if(pointerEnter.tag == “BagGrid”){

                GridView  gv = pointerEnter.GetComponent<GridView>();

               bool  isChange =true; //判断是否交换

 

               if(player.bagArray[gv.index] == null){

                    ChangeUINullGrid(gird,gv); //

                }else{

                      //判断物体的类型

                      //如果不是装备则UI不交换

                   if(player.bagArray[gv.index].type == ToolType.ATK){

                       ChangeUIFullGrid(grid,gv);  //不空

                    }else{

                       isChange =false;

                    }

                }

 

                if(isChange){

                   //数据

                  ToolModel  tm = player.bagArray[gv.index];

                 player.bagArray[gv.index] = player.gearArray[grid.index];

                 player.gearArray[grid.index] = tm;

                }

            }

        }

 

        targetTransform.SetParent(grid.transform); //返回原来的格子

        targetTransform.localPosition = Vector3.zero; //在父物体的位置localPosition0

        targetTransform = null; //0

    }

 

    public void ClickTool(GridView  gridPointerEventData pointData){

        if(player.bagArray[grid.index] != null){

            if(player.bagArray[grid.index].type == ToolType.HP){

               //数据更新

               player.HP+= player.bagArray[grid.index].value;

               player.bagArray[grid.index] = null;

 

               //UI更新

               bagView.playerInfoView.hpView.HPValue.text = player.HP.ToString();

               grid.contentImage.sprite = null;

              grid.contentImage.gameObject.SetActive(false);

            }

        }

    }

 

    #region 改变UI

 

    //放到没有物品的格子中(destination: 目标格子)

    void ChangeUINullGrid(GridView  origin,  GridView destination){

        destination.contentImage.gameObject.SetActive(true); //目的格子图片激活

    

        //将源格子的图片赋值给目的格子

        destination.contentImage.sprite = origin.contentImage.sprite;

        origin.contentImage.sprite = null;  //将源格子图片清空

        origin.contentImage.gameObject.SetActive(false); //将源格子图片取消激活

    }

 

    //放到有物品的格子中

    void ChangeUIFullGrid(GridView origin,  GridView destination){

        Sprite s = destination.contentImage.sprite;

        destination.contentImage.sprite = origin.contentImage.sprite;

        origin.contentImage.sprite = s;

    }

 

    #endregion

 

}


##Model/

++Model/

++++PlayerModelScript.cs

++++ToolModel.cs

###PlayerModelScript.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\Model\PlayerModelScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class  PlayerModelScript{

    public  string playerName{get;set; }  //姓名

    public int HP{get;set; }  //血量

    public int  ATK{get;set; }  //攻击力

    public ToolModel[]  gearArray;  //装备区

    public  ToolModel[]  bagArray;  //背包

 

    public PlayerModelScript(string  name,int hp,int  atk){

        playerName = name;

        HP = hp;

        ATK = atk;

        gearArray = new ToolModel[8];  //装备

        bagArray = new ToolModel[20];  //背包

    }

}


###ToolModel.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\Model\ToolModel.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public enmu  ToolType{

    HP,

    ATK

}

 

//立钻哥哥:道具Model

public  class  ToolModel{

    public string  toolName{set;get; }  //道具名字

    public ToolType type{set;get; } //道具类别

    public int  value{set;get; } //数值

    public Sprite  toolSprite{set;get; }  //道具图片

 

    //构造方法

    public  ToolModel(string  name, ToolTypett,  int v, Sprite sp){

        toolName = name;

        type = tt;

        value = v;

        toolSprite = sp;

    }

}


##View/

++View/

++++BagView.cs

++++GridView.cs

++++HPView.cs

++++PlayerBagView.cs

++++PlayerInfoView.cs


###BagView.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\View\BagView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//挂载在BagView上,目的收集子视图View

public class BagView :MonoBehaviour{

    public PlayerInfoView  playerInfoView;  //人物界面

    public  PlayerBagView  playerBagView;  //背包界面

}


###GridView.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\View\GridView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.EventSystems;

//using System.Net.NetworkInformation;

 

//移动的接口

public interface IMoveHandle{

    void BeginMove(GridView  grid,  PointerEventData pointData);  //鼠标进入

    void Move(GridView  grid,  PointerEventData pointData); //移动

    void EndMove(GridView  grid,  PointerEventData pointData);  //结束移动

    void ClickTool(GridView  grid,  PointerEventData pointData); //点击的道具

}

 

public  class  GridView : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler,IPointerClickHandler{

    public Image  contentImage;

    public int index{set;get; }  //格子创建时的下标,标记它的目的是为了在交换物品或者移动时候和数组元素对应

    public IMoveHandle moveHandle; //将接口定义为视图的字段或者属性

 

    //实现继承过来接口里边的内容

    public void OnBeginDrag(PointerEventData eventData){

        moveHandle.BeginMove(this,eventData);

    }

 

    public void OnDrag(PointerEventData  eventData){

        moveHandle.Move(this,eventData);

    }

 

    public void OnEndDrag(PointerEventData  eventData){

        moveHandle.EndMove(this,eventData);

    }

 

    public void OnPointerClick(PointerEventData  eventData){

        moveHandle.ClickTool(this,eventData);

    }

}


###HPView.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\View\HPView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

//获得它下边的两个文本

public  class  HPView : MonoBehaviour{

    public  Text HpText;

    public Text HPValue;

}


###PlayerBagView.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\View\PlayerBagView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public  class PlayerBagView: MonoBehaviour{

    public RectTransform gridGroupView;

}


###PlayerInfoView.cs

C:\000-ylzServ_DemoPro\小案例004\Bag\Assets\Scripts\View\PlayerInfoView.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//任务属性界面脚本(目的:收集其子物体关于View的脚本)

public  class  PlayerInfoView : MonoBehaviour{

    public  RectTransform  gridGroupView; //格子视图

    public HPView  hpView;

}




#小案例005、塔防Demo

++小案例005、塔防Demo

++++BulletScript.cs

++++CameraMoveScript.cs

++++EndScript.cs

++++GameDataScript.cs

++++InitMonsterScript.cs

++++InitTowerScript.cs

++++MonsterScript.cs

++++TowerFireScript.cs




###BulletScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\BulletScript.cs

using UnityEngine;

using System.Collections;

 

//该脚本功能是控制子弹的发射和碰撞检测(加到粒子特效上,模拟子弹)

public class BulletScript :MonoBehaviour{

    public  Transform  target;  //子弹要攻击的目标

    public float bulletSpeed=3; //子弹的飞行速度

    public float damager=100;  //子弹的伤害值

 

    void Update(){

        if(target){

            Vector3 dir =target.position-transform.position;  //得到子弹要飞行的向量

            Transform.position += dir*Time.deltaTime*bulletSpeed; //子弹移动

        }else{

            Destroy(gameObject);  //如果目标是空,把子弹销毁

        }

    }

 

     void  OnTriggerEnter(Collider  other){

        if(other.tag == “monster”){

            Other.GetComponent<MonsterScript>().health -= damage; //怪物掉血

            Destroy(this.gameObject);  //把子弹销毁掉

        }

    }

}


###CameraMoveScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\CameraMoveScript.cs

using UnityEngine;

using System.Collections;

 

public  class  CameraMoveScript : MonoBehaviour{

    public float  moveSpeed =3;

 

    void Update(){

        float hor  = Input.GetAxis(“Horizontal”);

        float ver  = Input.GetAxis(“Vertical”);

        transform.position += new Vector3(hor,0,ver) *Time.deltaTime*moveSpeed;

    }

}



###EndScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\EndScript.cs

using UnityEngine;

using System.Collections;

 

//加在End物体上,功能是当怪物触发后,把怪物销毁

public  class  EndScript : MonoBehaviour{

    void OnTriggerEnter(Collider other){

        if(other.tag ==  “monster”){

            Debug.Log(tttt);

            Destroy(other.gameObject);

        }

    }

}


###GameDataScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\GameDataScript.cs

using UnityEngine;

using System.Collections;

using System;

 

//功能是控制所生成怪物的数量,速度和时间间隔,主要的思路是用一个结构体数组,数组的长度即为波数,每一波对应数组里面的一个元素,读取结构体里面的数据。

public  class  GameDataScript : MonoBehaviour{

    public  static GameDataScript Instance;

 

    public struct  Data{

        public float waitTime; //等待多长时间产生一波敌人

        public int monsterCount;  //每一波敌人的数量

        public float moveSpeed;  //每一波敌人的移动速度

    }

 

    //刚开始时的默认数据

    float  waitTimeDefault =3;

    int  monsterCountDefault= 3;

    float  moveSpeedDefault =2;

    public Data[] monsterData; //每一波所对应的数据

 

    void  Awake(){

        Instance = this;

    }

 

    void Start(){

        monsterData = new Data[10];

        for(int i =0; i < monsterData.Lengthi++){

            //第一次循环时把默认数据赋值给第一个元素

            monsterData[i].waitTime =waitTimeDefault;

            monsterData[i].monsterCount = monsterCountDefault;

            monsterData[i].moveSpeed =moveSpeedDefault;

 

            //每循环一次数据增加

            waitTimeDefault += 0.5f;

            monsterCountDefault += 1;

            moveSpeedDefault += 0.3f;

        }

    }

}


###InitMonsterScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\InitMonsterScript.cs

using UnityEngine;

using System.Collections;

 

//怪物生成(加到Start空物体上)

public  class  InitMonsterScript : MonoBehaviour{

    puiblic  GameObject monster; //怪物预设体

    float  timer; //计时器

    int  index = 0; //生成怪物的波数

    bool isInit = false  //当前是否正在生成怪物

    int  monsterCount = 0;  //一波中怪物的数量

    bool isGaming=true; //是否在游戏中

 

    void Update(){

        if(isGaming){

            timer += Time.deltaTime;

 

            //读取Data数组中index中相对应的元素,再找到里面对应的相关数据

            //1、先得到时间间隔

            float timeInterval  = GameDataScript.Instance.monsterData[index].waitTime;

        

            //2、如果计时器达到等待生成怪物的时间,并且没有初始化怪物,则把计时器归0,开始初始化怪物

            if(!isInit && timer > timeInterval){

               timer = 0;

               isInit =true;

 

            }else if(isInit){

                 //如果能初始化怪物

               if(timer > 1){

                    //每隔一秒生成一个怪物

                   timer =0;

                    GameObject  currentMonster = Instantiate(monster,transform.position,Quaternion.identity)  as GameObject; //生成怪物

                     currentMonster.GetComponent<UnityEngine.AI.NavMeshAgent>().speed = GameDataScript.Instance.monsterData[index].moveSpeed;  //把数据组中的速度赋值给导航中的速度

                    monsterCount++;  //怪物数量增加

 

                   if(monsterCount == GameDataScript.Instance.monsterData[index].monsterCount){

                        //如果怪物生成的数量与给定的数量相同

                       monsterCount = 0;  //数据归零

                       index++; //进入下一波

                       isInit = false; //不能再进行初始化了

 

                       if(index >GameDataScript.Instance.monsterData.Length-1){

                            //说明波次已经够了,此时游戏结束

                          isGaming =false;

                        }

                    }

               }

           }

       }

    }

}


###InitTowerScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\InitTowerScript.cs

using UnityEngine;

using System.Collections;

 

//加到空GameController上,主要的功能是点击鼠标左键,创建炮塔

public  class InitTowerScript :MonoBehaviour{

    public GameObject  tower;

    RaycastHit hit;

 

    void  Update(){

        //如果按下鼠标左键

        if(Input.GetMouseButtonDown(0)){

            //从摄像机到鼠标点击位置发出一条射线

            if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out  hit)){

               Debug.Log(hit.collider.name);

            

                //检测点击到的是否是木箱,如果名字中包含Tower,并且没有子物体

               if(hit.collider.name.IndexOf(“Tower”) != -1 && hit.collider.transform.childCount ==0){

                   Vector3  pos =hit.collider.transform.position+Vector3.up* 2.65f;

                   GameObject  gun = Instantiate(tower,pos,Quaternion.identity) as GameObject; //生成大炮

                   gun.transform.SetParent(hit.collider.transform);  //给生成的炮塔设置父物体

                }

            }

        }

    }

}


###MonsterScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\MonsterScript.cs

using UnityEngine;

using System.Collections;

 

//功能是控制怪物的运动(脚本加到Monster上)

public  class  MonsterScript :MonoBehaviour{

    public float  health = 100; //生命值

    UnityEngine.AI.NavMeshAgent  nav; //导航组件

    Transform  end;  //终点

    Animation  ani;  //动画组件

 

    void  Awake(){

        nav = GetComponent<UnityEngine.AI.NavMeshAgent>();

        ani = GetComponent<Animation>();

        end = GameObject.FindWithTag(“end”).transform;

    }

 

    void  Start(){

        nav.destination = end.position;

    }

 

    void  Update(){

        //如果血量小于等于0

        if(health <0){

            GetComponent<CapsuleCollider>().enabled = false;  //关闭碰撞器

            ani.CrossFade(“Dead”);

            Destroy(gameObject,1); //1秒钟后销毁自己

        }

    }

}


###TowerFireScript.cs

D:\000-ylzServ_DemoPro\小案例005\Assets\DemoBak\Homework\TowerFireScript.cs

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

 

public  class  TowerFireScript :MonoBehaviour{

    public  GameObject  bullet;  //生成炮弹

    public float  fireRadius= 7f;  //攻击半径

    public float rotateSpeed=3f;  //炮头转向速度

    public float distance=0.5f;  //炮头与炮身之间的距离

    public float bullectMoveSpeed=5f; //子弹飞行的速度

    public  Transform  fireTarget; //攻击的目标

    public float  fireTimeInterval=0.5f;  //发射子弹的间隔时间

    private float timer=0;  //计时器

    private  Queue<Transform>  monsterQueue;  //怪物的队列

 

    void Awake(){

        monsterQueue = new Queue<Transform>();

    }

 

    void  Start(){

    }

 

    void  Update(){

        //如果攻击目标为空

        if(fireTarget == null){

            if(monsterQueue.Count>0){

               fireTaget = monsterQueue.Dequeue();

            }

        }else{

            Fire();

        }

    }

 

    //当怪物进入触发器中,把该怪物添加到要攻击的队列中

    void  OnTriggerEnter(Collider  other){

        Debug.Log(enter);

 

        //如果是怪物

        if(other.tag == “monster”){

            monsterQueue.Enqueue(other.transform);

        }

    }

 

    //离开触发

    void  OnTriggerExit(Collider  other){

        Debug.Log(exit);

        if(other.tag == “monster”){

            //如果是当前正在攻击的目标

             if(other.transform == fireTarget){

               fireTarget= null;  //把攻击目标设置为空

            }else{

                 //如果队列不为空

                if(monsterQueue.Count>0){

                    monsterQueue.Dequeue();

                 }

            }

        }

    }

 

    void Fire(){

        Vector3 dir =fireTarget.position-transform.position;

        Quaternion rotation = Quaternion.LookRotation(dir);

        transform.rotation =Quaternion.Lerp(transform.rotation,rotation,Time.deltaTime*rotateSpeed);

        Debug.DrawRay(transform.position, dir,Color.red);

        Debug.DrawRay(transform.position, transform.forward * 10,Color.green);

 

        if(Vector3.Angle(dir,transform.forward) <5){

            InitBullet();

         }

    }

 

    void InitBullet(){

        timer += Time.deltaTime;

        if(timer >fireTimeInterval){

            timer = 0;

            Vector3 point = transform.GetChild(0).position+transform.GetChild(0).forward*distance;

            GameObject currentBullet =Instantiate(bullet,point,Quaternion.identity)asGameObject;

            currentBullet.GetComponent<BulletScript>().target = this.fireTarget;

            currentBullet.GetComponent<BulletScript>().bulletSpeed = this.bulletMoveSpeed;

        }

     }

}




#小案例006、秘密行动DemoNG进行中)

++小案例006、 秘密行动Demo

++++AlarmLight.cs

++++CameraMovement.cs

++++CCTVPlayerDetection.cs

++++DoorAnimation.cs

++++EnemyAI.cs

++++EnemyAnimation.cs

++++EnemyShooting.cs

++++EnemySight.cs

++++HashIDs.cs

++++KeyPickup.cs

++++LaserController.cs

++++LaserSwitchDeactivation.cs

++++LastPlayerSighting.cs

++++LiftDoorsTracking.cs

++++PlayerHealth.cs

++++PlayerInventory.cs

++++PlayerMovement.cs

++++SyncDoor.cs

++++Tags.cs





++秘密行动思维导图

---0、添加Tag脚本

---1、添加场景模型

---2、创建一个空游戏物体

---3、添加英雄char_ethan

---4、添加平行光

---5、给主摄像机添加脚本,用来控制摄像机的移动

---6、在GameController上添加子物体SecondSound

---7、给警报喇叭添加标签

---8、给GameController添加脚本LastPlayerSighting

---9、添加激光灯

---10、创建空物体Doors,用来管理自动门

---11、创建空物体SwitchUnits来控制激光门的开和关

---12、添加钥匙卡

---13、添加CCTV摄像机

---14、添加电梯外面的开关门

---15、添加电梯

---16、放置巡逻点

---17、小机器人

---18、添加手枪

---======================---===============---

 

++++0、添加Tag脚本,该脚本可以直接取到tag值,不加到任何游戏物体上。

 

++++1、添加场景模型

--1.1、添加 env_stealth_static

--1.2、添加卡车 prop_battleBus

--1.3、添加网格碰撞器 env_stealth_collision

 

++++2、创建一个空游戏物体

--2.1、命名GameController

--2.2、添加声音组件播放背景音乐

    ---playonawake = true,

    ---loop = true,

    ---volume = 1

--2.3、添加脚本HashID,用来给动画控制设置参数。

--2.4、添加tagGameController

 

++++3、添加英雄 char_ethan

--3.1、添加胶囊碰撞器

--3.2、添加刚体,冻结所有的旋转以及y轴方向的位置

--3.3、添加声音组件,声音片段为脚步声

--3.4、添加动画控制器PlayerAnimator

--3.5、添加脚本PlayerHealth,用来控制英雄的少血以及死亡

--3.6、添加脚本PlayerMove,用来控制英雄的移动

--3.7、添加tagPlayer

 

++++4、添加平行光

--4.1、做了警报灯,颜色为红色,intensity=0

--4.2、添加脚本AlarmLight脚本组件,用来控制警报灯由明变暗再由暗变明

--4.3、添加tagAlarmLight

 

++++5、给主摄像机添加脚本,用来控制摄像机的移动

--5.1Editor/ProjectSetting/Physic/Hit Triggers取消勾选(否则射线会检测触发器,取消后只会检测碰撞器)

--5.2、添加脚本CameraMove

 

++++6、在GameController上添加子物体SecondSound

--6.1、给子物体添加AudioSource组件

--6.2、添加声音片段music_panic

--6.3、设置声音的初始值为0

--6.4PlayOnAwakeLoop勾选

 

++++7、给警报喇叭添加标签

--7.1、给prop_megaphon添加siren标签

--7.2、给六个喇叭添加AudioSource组件

--7.3、添加声音片段alarm_trigger

--7.4、设置声音的初始值为0

--7.5PlayOnAwakeLoop勾选

 

++++8、给GameController添加脚本LastPlayerSighting

 

++++9、添加激光灯

--9.1、创建空物体Lasers用来管理激光门

--9.2、把fx_laserFence_lasers插到场景中并放到合适的位置(大小和旋转)

--9.3、添加AudioSource组件,加上laser_hum声音片段,把LoopPlayOnAwake勾选,音量设置为1

--9.4、添加点灯源组件,颜色为红色,Range=5Intensity=1.5Bounce=1

--9.5、添加一个Box触发器,用来进行触发检测

--9.6、添加脚本LaserController

 

++++10、创建空物体Doors,用来管理自动门

--10.1、把door_generic_slide拖到合适的位置

--10.2、添加球形触发器,半径为1.5,高为1

       在门的子物体上添加盒形碰撞器,防止没有钥匙的时候,玩家可以直接穿透门

--10.3、添加AudioSource组件,和door_open声音片段,最小距离1,最大距离为5

--10.4、添加DoorAnimator动画控制器组件,给自动门添加动画,添加播放声音的事件

--10.5、添加脚本DoorAnimation

 

++++11、创建空物体SwitchUnits来控制激光门的开和关

--11.1、拖动prop_switchUnit_screen到场景中

--11.2、在父物体上添加Box碰撞器,在子物体上添加Box触发器,在子物体上添加声音组件

--11.3、添加脚本 LaserSwitchDeactivation

 

++++12、添加钥匙卡

--12.1、拖动prop_keycard到场景中合适的位置

--12.2、添加球形触发器

--12.3、添加点光源,颜色为蓝色

--12.4、添加动画控制器组件

 

++++13、添加CCTV摄像机

--13.1Y轴旋转180

--13.2、子物体_body x轴旋转30

--13.3、给子物体_joint添加帧动画

--13.4、在_body子物体下添加空物体trigger,沿X轴旋转30度,并添加MeshCollider组件,添加prop_cctvCam_collision,并使其变为触发器

--13.5、添加Light组件,选择spot的灯光,Range=40, Angle=62intensity=4, bounce=1, cookie选择fx_cameraView_alp

--13.6、给trigger子物体添加脚本CCTV

 

++++14、添加电梯外面的开关门

--14.1、拖动door_exit_outer到合适的位置,沿y轴旋转-90

--14.2、添加球形碰撞器

--14.3、添加声源组件,添加open_door声音片段

--14.4、添加动画控制器RedDoorAnimator

--14.5、添加DoorAnimation脚本组件

 

++++15、添加电梯

--15.1、拖动prop_lift_exit到电梯井里面,并沿Y轴旋转-90

--15.2、添加声源组件,并添加endgame声音片段

--15.3、给子物体_carriage添加声源组件,添加lift_rise声音片段

--15.4、给_carriage添加四个box碰撞器:

---第一个设置为trigger

---第二个center.z=2(其余不变), size.z=0.15(其余不变)

---第三个center.z=2(其余不变),size.z=0.15(其余不变)

---第四个center.x=1.87,其余为0size.x=0.2

--15.5、给carriage添加脚本LiftDoor

--15.6、给子物体door_inner添加脚本SyncDoor

 

++++16、放置巡逻点

 

++++17、小机器人

--17.1、添加小机器人的动画控制器EnemyAnimatorController

--17.2、在hashids里面添加新的动画参数值

--17.3、添加动画遮罩EnemyShootingMask

--17.4、设置射击层的过渡条件

--17.5、设置导航路面

--17.6、给小机器人添加animator组件,刚体组件,胶囊体碰撞器,球形触发器导航组件

--17.7、添加EnemySight组件

 

++++18、添加手枪

--18.1、在机器人char_robotGuard_RightHandThumb1下添加子物体prop_sciFiGun_low

--18.2、在枪的子物体下添加子物体Effect,添加灯光组件以及linerander组件,二者都设置为不可用。

--18.3、给射击的动画片段添加动画曲线

--18.4、添加脚本EnemyAnimation

--18.5、在场景中添加小机器人巡逻的小旗帜

--18.6、添加脚本EnemyAI

--18.7、添加脚本EnemyShooting


###AlarmLight.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\AlarmLight.cs

using UnityEngine;

using System.Collections;

 

public class AlarmLight:MonoBehaviour{

    public  bool  alarmOn=false;    //是否开启警报

    public float  turnSpeed=3f;    //警报灯切换速度

    private float highIntensity=2f;    //高光强

    private float  lowIntensity=0f;    //低光强

    private float  targetIntensity=0f;    //目标光强

    private  Light  alarmLight;    //警报灯光

 

    void  Awake(){

        alarmLight = GetComponent<Light>();    //获取警报灯

        targetIntensity = highIntensity;    //设置目标光强初始值为高光强

    }

 

    void  Update(){

        //如果警报开启

        if(alarmOn){

            //警报灯切换到目标光强

            alarmLight.intensity =  Mathf.Lerp(alarmLight.intensity,targetIntensity,Time.deltaTime*turnSpeed);

 

            //如果当前光强强度到达了目标光强,需要切换目标

            if(Math.Abs(targetIntensity-alarmLight.intensity) <0.05f){

               //如果当前目标是高光强

               if(targetIntensity == highIntensity){

                   targetIntensity = lowIntensity;   //切换目标为低光强

                }else{

                   targetIntensity =highIntensity;    //否则切换目标为高光强

                }

            }

        }else{

             //警报灯渐变到低光强

            alarmLight.intensity  = Mathf.Lerp(alarmLight.intensity,lowIntensity,Time.deltaTime*turnSpeed);

 

            //如果已经到达了低光强

            if(alarmLight.intensity < 0.05f){

                //直接切换光强为0,减少CPU的计算

               alarmLight.intensity =lowIntensity;    

            }

        }

    }

}


###CameraMovement.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\CameraMovement.cs

using UnityEngine;

using System.Collections;

 

public  class CameraMovement:MonoBehaviour{

    public float moveSpeed= 3f;    //摄像机移动速度

    public float  turnSpeed=10f;    //摄像机旋转速度

    private  Transform  player;    //玩家

    private  Vector3  direction;    //摄像机与玩家之间的方向向量

    private  RaycastHit  hit;    //射线碰撞检测器

    private float  distance;    //摄像机与玩家的最小距离

    private  Vector3[]  currentPoints;    //当前所有的点

 

    void  Awake(){

        player = GameObject.FindWithTag(Tags.Player).transform;

        currentPoints = new Vector3[5];

     }

 

     void  Start(){

        //计算玩家头顶方向与摄像机的距离

        distance = Vector3.Distance(transform.position,player.position) -0.5f;

 

        //游戏开始时玩家与摄像机之间的方向向量

        direction = player.position-transform.position;

     }

 

    void  Lateupdate(){

        Vector3 startPoint =player.position-direction;    //第一个点

        Vector3 endPoint =player.position+Vector3.up*distance;    //最后一个点

        currentPoint[1] = Vector3.Lerp(startPoint,endPoint,0.25f);    //第二个点

        currentPoint[2] = Vector3.Lerp(startPoint,endPoint,0.5f);    //第三个点

        currentPoint[3] = Vector3.Lerp(startPoint,endPoint,0.75f);    //第四个点

 

        //放到数组中

        currentPoints[0] = startPoint;

        currentPoints[4] = endPoint;

 

         //创建一个点,用来存储选择好可以看到玩家的点

        Vector3 viewPosition =currentPoints[0];

 

        //遍历五点

        for(int i = 0;  i <5;  i++){

            if(CheckView(currentPoints[i])){

               viewPosition = currentPoints[i];    //更新合适的点

               break;

            }

        }

 

        //摄像机移动到指定点

        transform.positionVector3.Lerp(transform.position,viewPosition,Time.deltaTime*moveSpeed);

        SmoothRotate();    //执行平滑旋转

    }

 

    //检测是否可以看到玩家

    //return true:看到了,false:没看到

    //param pos:射线发射点

    bool  checkView(Vector3 pos){

         Vector3 dir = player.position -pos; //计算方向向量

    

        //发射射线

        if(Physics.Raycast(pos,dir, out hit)){

            //如果看到了

            if(hit.collider.tag == Tags.Player){

               return  true;

            }

        }

 

        return  false;

    }

 

    //平滑旋转

    void SmoothRotate(){

        //计算方向向量

        Vector3 dir = player.position + Vector3.up* 0.2f-transform.position;

        Quaternion qua =Quaternion.LookRotation(dir);    //转换为四元数

    

        //平滑移动

        transform.rotation =Quaternion.Lerp(transform.rotation,qua,Time.deltaTime*turnSpeed);

 

        //优化Y轴和Z轴旋转

        transform.eulerAngles = new Vector3(transform.eulerAngles.x,0, 0);

    }

}


###CCTVPlayerDetection.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\CCTVPlayerDetection.cs

using UnityEngine;

using System.Collections;

 

public  class  CCTVPlayerDetection:MonoBehaviour{

    private  LastPlayerSighting  lastPlayerSighting;    //传输警报位置

 

    void  Awake(){

        lastPlayerSighting = GameObject.FindWithTag(Tags.GameController).GetComponent<LastPlayerSighting>();

    }

 

    void OnTriggerEnter(Collider other){

        //如果是玩家,同步警报位置

        if(other.tag == Tags.Player){

            lastPlayerSighting.alarmPositon =other.transform.position;

        }

    }

}


###DoorAnimation.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\DoorAnimation.cs

using UnityEngine;

using System.Collections;

 

public  class  DoorAnimation:MonoBehaviour{

    public  bool  needKey = false;    //当前门是否需要钥匙

    public  AudioClip  refuseAud;    //拒绝开门的声音片段

    private  bool  playerIn=false;    //玩家进入到了大门触发器范围内

    private int  count=0;    //人数

    private Animator  ani;

    private  AudioSource  aud;

    private PlayerInventory  playerInventory;    //玩家是否拥有钥匙的脚本

 

    void Awake(){

        ani = GetComponent<Animator>();

        aud = GetComponent<AudioSource>();

        playerInventory = GameObject.FindWithTag(Tags.Player).GetComponent<PlayerInventory>();

    }

 

    void  OnTriggerEnter(Collider other){

        //如果进来的是玩家或机器人

        if(other.tag ==Tags.Player|| (other.tag ==Tags.Enemy&&other.GetType() ==typeof(CapsuleCollider))){

            count++;    //人数递增

 

            //如果是玩家

            if(other.tag == Tags.Player){

               playerIn =true;    //设置玩家进入的标志位

            

                //如果玩家没有钥匙

               if(!playerInventory.hasKey&&needkey){

                   //播放拒绝声音

                   AudioSource.PlayClipAtPoint(refuseAud,transform.position);

                }

            }

        }

    }

 

    void  OnTriggerExit(Collider  other){

        //如果进来的是玩家或机器人

        if(other.tag == Tags.Player|| (other.tag ==Tags.Enemy&&other.GetType() == typeof(CapsuleCollider))){

            count--;    //人数递减

        

            //如果是玩家

            if(other.tag ==Tags.Player){

               playerIn =false;    //设置玩家进入的标志位

            }

        }

    }

 

    void  Update(){

         //不需要钥匙的时候

        if(!needKey){

             if(count > 0){

               ani.SetBool(HashIDs.DoorOpen,true);    //门打开

             }else{

               ani.SetBool(HashIDs.DoorOpen, false);    //门关闭

            }

        }else{

            //玩家带着钥匙进去

            if(playerIn&&playerInventory.hasKey){

               ani.SetBool(HashIDs.DoorOpen, true);

            }else{

               ani.SetBool(HashIDs.DoorOpen, false);

            }

        }

    }

 

    //动画帧事件,播放开关门声音

    public void PlayVoice(){

        if(Time.time > 0.1f){

            aud.Play();    //播放声音

        }

    }

}


###EnemyAI.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\EnemyAI.cs

using UnityEngine;

using System.Collections;

 

public class EnemyAI:MonoBehaviour{

    public Transform[]  wayPoints;    //巡逻点

    public float  chasingSpeed=6f;    //追捕速度

    public float  patrallingSpeed= 2.5f;   //巡逻速度

    public float chasingWaitTime=3f;    //巡视时间

    private float  chasingTimer;    //追捕等待计时器

    private float patrallingTimer;    //巡逻等待计时器

    private EnemySight  enemySight;

    private LastPlayerSighting  lastPlayerSighting;   

    private UnityEngine.AI.NavmeshAgent  nav;

    private int index;   //巡逻目标索引号

    private PlayerHealth  playerHealth;

 

    void  Awake(){

        enemySight = GetComponent<EnemySight>();

        lastPlayerSighting = GameObject.FindWithTag(Tags.GameController).GetComponent<LastPlayerSighting>();

        nav = GetComponent<UnityEngine.AI.NavMeshAgent>();

        playerHealth = GameObject.FindWithTag(Tags.Player).GetComponent<PlayerHealth>();

        index = 0;

    }

 

    void  Update(){

        if(enemySight.playerInSight&&playerHealth.health>0){

            Shooting();    //射击

        }else if(enemySight.personalAlarmPosition!=lastPlayerSighting.normalPosition&&playerHealth.health>0){

            Chasing();    //追捕

        }else{

            Patrolling();    //巡逻

        }

    }

 

    //射击

    void Shooting(){

        nav.Stop();   //导航停止

    }

 

    //追捕

    void Chasing(){

        nav.Resume();    //恢复导航

        nav.speed = chasingSpeed;    //加快速度

        nav.SetDestination(enemySight.personalAlarmpositon);    //设置导航目标

 

        //到达了警报位置

        if(nav.remainingDistance -nav.stoppingDistance<0.5f){

            chasingTimer += Time.deltaTime;    //追捕等待计时器计时

        

            //达到等待时间

            if(chasingTimer > chasingWaitTime){

               chasingTimer =0;    //重置计时器

 

                //警报解除

                lastPlayerSighting.alarmPosition =lastPlayerSighting.normalPosition;

             }

         }else{

            chasingTimer = 0;    //重置计时器

        }

    }

 

    //巡逻

    void Patrolling(){

        nav.speed = patrallingSpeed;   //巡逻速度

        nav.SetDestination(wayPoints[index].position);    //设置巡逻目标

 

        //达到巡逻点

        if(nav.remainingDistance- nav.stoppingDistance< 0.5f){

            patrallingTimer += Time.deltaTime;    //计时器计时

 

            //计时器完成本次计时

            if(patrallingTimer >chasingWaitTime){

                //更新下一个巡逻点索引号

                //index = ++index % wayPoints.Length;

               index++;

               index =index%wayPoints.Length;

               patrallingTimer = 0;    //计时器清零

             }

          }else{

             patrallingTimer = 0;    //计时器清零

         }

    }

}


###EnemyAnimation.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\EnemyAnimation.cs

using UnityEngine;

using System.Collections;

 

public  class  EnemyAnimation:MonoBehaviour{

    public float  deadZone=4;    //死角度数

    public float  dampSpeedTime= 0.1f;    //设置动画参数的延迟时间

    public float  dampAngularSpeedTime=0.1f;  

 

    private UnityEngine.AI.NavMeshAgent  nav;

    private EnemySight enemySight;

    private  Transform  player;

    private  Animator  ani;

 

    void  Awake(){

        nav = GetComponent<UnityEngine.AI.NavMeshAgent>();

        enemySight = GetComponent<EnemySight>();

        player = GameObject.FindWithTag(Tags.Player).transform;

        ani = GetComponent<Animator>();

        deadZone *= Mathf.Deg2Rad;    //死角度数转为弧度

    }

 

    void  OnAnimatorMove(){

        nav.velocity = ani.deltaPosition/Time.deltaTime;

        transform.rotation =ani.rootRotation;

    }

 

    void  Update(){

        float speed = 0;

        float angularSpeed =0;

 

        //如果看到了玩家

        if(enemySight.playerInSight){

            speed = 0;    //停下来

            angularSpeed = FindAngle();    //角速度,按导航转向

 

            //如果角度过小,进入死角

            if(Mathf.Abs(angularSpeed) < deadZone){

               angularSpeed =0;    //停止用动画转身

               transform.LookAt(player);    //机器人直接看向玩家

            }

        }else{

            //直线速度 =机器人前方的投影向量的模

            speed = Vector3.Project(nav.desiredVelocity,transform.forward).magnitude;

            angularSpeed = FindAngle();    //角速度,按导航转向

        }

 

        //设置动画参数

        ani.SetFloat(HashIDs.Speed,speed,dampSpeedTime,Time.deltaTime);

        ani.SetFloat(HashIDs.AngularSpeed,angularSpeed,dampAngularSpeedTime,Time.deltaTime);

    }

 

     float FindAngle(){

         Vector3 dir = nav.desiredVelocity;    //期望速度

 

         //机器人前方与期望速度形成的夹角

        float angle = Vector3.Angle(dir,transform.forward);    

 

        //计算两向量的法向量

        Vector3 normal = Vector3.Cross(transform.forward,dir);

 

        //如果期望速度在机器人左方,角度为负

        if(normal.y <0){

            angle *= -1;

        }

 

         //将角度转换为弧度

        angle *= Mathf.Deg2Rad;

 

        //如果期望速度为0

        if(dir ==Vector3.zero){

            angle = 0;

        }

 

        return  angle;

    }

}


###EnemyShooting.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\EnemyShooting.cs

using UnityEngine;

using System.Collections;

 

public class  EnemyShooting:MonoBehaviour{

    public float  damage= 10;    //一枪伤害

 

    private Animator  ani;

    private  Light  shootLight;

    private LineRenderer shootLine;

    private  bool  shooting = false;

    private  Transform player;

    private PlayerHealth  playerHealth;

 

    void Awake(){

        ani = GetComponent<Animator>();

        shootLight = GetComponentInChildren<Light>();

        shootLine = GetComponentInChildren<LineRenderer>();

        player = GameObject.FindWithTag(Tags.Player).transform;

        playerHealth = player.GetComponent<PlayerHealth>();

    }

 

    void  Update(){

        //射击开始

        if(ani.GetFloat(HashIDs.shot) > 0.5f && !shooting){

            Shooting();

        }elseif(ani.GetFloat(HashIDs.Shot) < 0.5f){

            shooting = false;

            shootLight.enabled =false;

            shootLine.enabled =false;

        }

    }

 

    //射击

    void Shooting(){

        shootLight.enabled = true;    //打开闪光

    

        //绘制激光线

        shootLine.SetPosition(0, shootLine.transform.parent.position);

        shootLine.SetPosition(1, player.position+Vector3.up*1.5f);

        shootLine.enabled =true;

        shooting = true;    //正在射击

        playerHealth.TakeDamage(damage);    //计算伤害

    }

 

    void OnAnimatorIK(int  layer){

        float weight = ani.GetFloat(HashIDs.AimWeight);    //获取曲线中的权重

        ani.SetIKPositionWeight(AvatarIKGoal.RightHand,weight);    //设置IK权重

    

        //设置IK位置

        ani.SetIKPosition(AvatarIKGoal.RightHand,player.position+Vector3.up*1.5f);

    }

}


###EnemySight.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\EnemySight.cs

using UnityEngine;

using System.Collections;

 

public  class EnemySight:MonoBehaviour{

    public  bool  playerInSight= false;    //能够看到玩家

    public float  fieldOfView= 110f;    //机器人视野夹角

    private float  distanceOfView;    //机器人视野距离

    private  SphereCollider  sph;    //机器人触发器

    public Vector3  personalAlarmPosition;    //私人警报位置

    private  Vector3  previousAlarmPosition;    //上一帧的公共警报位置

    private LastPlayerSighting lastPlayerSighting;    //公共警报脚本

    private  RaycastHit  hit;    //射线碰撞检测器

    private  UnityEngine.AI.NavMeshAgent  nav;    //导航组件

    private PlayerHealth  playerHealth;    //玩家血量脚本

    private  Animator  ani;    //动画组件

 

    void Awake(){

        lastPlayerSighting = GameObject.FindWithTag(Tags.GameController).GetComponent<LastPlayerSighting>();

 

        //获取触发器

        sph = GetComponent<SphereCollider>();

        nav = GetComponent<UnityEngine.AI.NavMeshAgent>();

        playerHealth = GameObject.FindWithTag(Tags.Player).GetComponent<PlayerHealth>();

        ani = GetComponent<Animator>();

    }

 

    void  Start(){

        //私人警报初值为非警报位置

        personalAlarmPosition = lastPlayerSighting.normalPosition;

 

        //上一帧的公共警报位置初值也为非警报位置

        previousAlarmPosition = lastPlayerSighting.normalPosition;

    

        //获取视野距离

        distanceOfView = sph.radius;

    }

 

    void  Update(){

        //公共警报一旦发生变化  --->通知到PersonalAlarmPosition

        //PersonalAlarmPosition  --/-->不能通知给公共警报

 

        //如果上一帧的公共警报位置,与本帧的公共警报位置不一致

        if(previousAlarmPosition != lastPlayerSighting.alarmPosition){

            //将最新的公共警报位置通知到私人警报位置

            personalAlarmPosition = lastPlayerSighting.alarmPosition;

        }

 

        //获取本帧的公共警报位置

        previousAlarmPosition =lastPlayerSighting.alarmPosition;   

 

        //如果玩家血量正常

        if(playerHealth.health > 0){

            ani.SetBool(HashIDs.PlayerInSight,playerInSight);

        }else{

           ani.SetBool(HashIDs.PlayerInSight, false);

        }

    }

 

    void  OnTriggerStay(Collider other){

        //如果是玩家

        if(other.tag ==Tags.Player){

            playerInSight = false;    //重置

 

            //玩家与机器人的距离

            float distanceVector3.Distance(other.transform.position, transform.position);

 

            //计算机器人自身前方与方向向量之间的夹角

            float angular =  Vector3.Angle(dir, transform.forward);

 

            //满足视野范围内核距离范围内

            if(distance <distanceOfView &&angular<fieldOfView/2){

               if(Physics.Raycast(transform.position+Vector3.up*1.7f, dir,outhit)){

                   if(hit.collider.tag == Tags.Player){

                       playerInSight = true;    //可以看到玩家

 

                        //报警

                       lastPlayerSighting.alarmPosition = other.transform.position;  

                    }

                }

            }

 

            //听觉:如果机器人与玩家的导航路径在听觉路径范围内

            if(EnemyListening(other.transform.position)){

                //如果玩家发出了声音

               if(other.GetComponent<AudioSource>().isPlaying){

                    //赋值私人警报位置

                   personalAlarmPosition =other.transform.position;

                }

            }

        }

    }

 

    //机器人与玩家的导航距离在视觉范围内

    bool  EnemyListening(Vector3 playerPos){

        UnityEngine.AI.NavMeshPath path = new UnityEngine.AI.NavMeshPath();

 

        //如果导航可以到达玩家位置

        if(nav.CalculatePath(playerPos, path)){

            //用数组获取所有的路径点

            Vector3[]  points =new Vector3[path.corners.Length+2];    

            points[0] = transform.position;    //起点

            points[points.Length-1] = playerPos;    //终点

        

            //赋值中间的拐点

            for(inti =1;  i < points.Length-1;  i++){

               points[i] = path.corners[i -1];

            }

 

            float  navDistance= 0;    //导航距离

             //遍历计算距离

            for(int i =0; i < points.Length-1;  i++){

               navDistance +=Vector3.Distance(points[i],points[i +1]);

             }

 

            //导航距离在听觉距离范围内

            if(navDistance < distanceOfView){

                return  true;

             }

        }

 

         return  false;

     }

}


###HashIDs.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\HashIDs.cs

using UnityEngine;

using System.Collections;

 

public class  HashIDs :MonoBehaviour{

    public  static int  DoorOpen;

    public  static int  Speed;

    public static int  Sneak;

    public static int  AngularSpeed;

    public  static  int Dead;

    public  static int  PlayerInSight;

    public static int  Shot;

    public static int  AimWeight;

    public  static  int  LocomotionState;

 

    void  Awake(){

        DoorOpen = Animator.StringToHash(“DoorOpen”);

        Speed = Animator.StringToHash(“Speed”);

        Sneak = Animator.StringToHash(“Sneak”);

        AngularSpeed = Animator.StringToHash(“AngularSpeed”);

        Dead = Animator.StringToHash(“Dead”);

        PlayerInSight = Animator.StringToHash(“PlayerInSight”);

        Shot = Animator.StringToHash(“Shot”);

        AimWeight = Animator.StringToHash(“AimWeight”);

        LocomotionState = Animator.StringToHash(“Locomotion”);

    }

}


###KeyPickup.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\KeyPickup.cs

using UnityEngine;

using System.Collections;

 

public class  KeyPickup:MonoBehaviour{

    public AudioClip  pickAud;    //拾取到钥匙的声音

    private PlayerInventory  playerInventory;

 

    void Awake(){

        playerInventory = GameObject.FindWithTag(Tags.Player).GetComponent<PlayerInventory>();

    }

 

    void  OnTriggerEnter(Collider  other){

        if(other.tag == Tags.Player){

            playerInventory.hasKey = true;    //更换标志位,玩家获取到了钥匙

            AudioSource.PlayClipAtPoint(pickAudtransform.position);    //播放声音

            Destroy(gameObject);    //销毁自己

        }

    }

}


###LaserController.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\LaserController.cs

using UnityEngine;

using System.Collections;

 

public  class LaserController:MonoBehaviour{

    public  bool  isBlinking=false;    //激光是否是闪动的

    public float  blinkDeltaTime=3f;    //闪动间隔时间

    private float timer=0;    //计时器

    private LastPlayerSighting  lastPlayerSighting;    //玩家警报脚本

 

    void  Awake(){

        //找到玩家警报脚本

        lastPlayerSighting = GameObject.FindWithTag(Tags.GameController).GetComponent<LastPlayerSighting>();

    }

 

    void  Update(){

        timer += Time.deltaTime;    //计时器计时

    

        //到达计时器时间

        if(timer>= blinkDeltaTime && isBlinking){

            timer = 0;    //计时器归零

    

            //控制激光组件的显影

            GetComponent<MeshRenderer>().enabled = !GetComponent<MeshRenderer>().enabled;

            GetComponent<Light>().enabled = !GetComponent<Light>().enabled;

            GetComponent<AudioSource>().enabled = !GetComponent<AudioSource>().enabled;

            GetComponent<BoxCollider>().enabled = !GetComponent<BoxCollider>().enabled;

        }

    }

 

    //玩家触碰到激光

    void  OnTriggerEnter(Collider  other){

        //如果是玩家

        if(other.tag ==Tags.Player){

            //将玩家位置同步到警报位置

            lastPlayerSighting.alarmPosition = other.transform.position;

        }

    }

}


###LaserSwitchDeactivation.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\LaserSwitchDeactivation.cs

using UnityEngine;

using System.Collections;

 

public  class  LaserSwitchDeactivation:MonoBehaviour{

    public  GameObject controlledLaser;    //所控制的激光

    public  Material  unlockMat;    //解锁的屏幕材质

 

    //当玩家进入到电脑控制范围

    void  OnTriggerStay(Collider other){

        //当玩家按下Z

        if(Input.GetKeyDown(KeyCode.Z) && other.tag ==Tags.Player && controlledLaser.activeSelf){

            controlledLaser.SetActive(false);    //关闭激光

            GetComponent<MeshRenderer>().material = unlockMat;    //切换屏幕材质

            GetComponent<AudioSource>().Play();

        }

    }

}


###LastPlayerSighting.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\LastPlayerSighting.cs

using UnityEngine;

using System.Collections;

 

public  class LastPlayerSighting : MonoBehaviour{

    public  Vector3  alarmPosition = new  Vector3(1000,1000,1000);    //警报位置

    public  Vector3  normalPosition = new  Vector3(1000,1000,1000);    //非警报位置

    public float  turnSpeed=3f;    //声音切换速度

    private AlarmLight  alarmLight;    //警报灯脚本

    private  AudioSource  mainAudio;    //主背景音乐

    private  AudioSource  panicAudio;    //警报背景音乐

    private AudioSource[]  alarmAudios;    //警报喇叭声音

 

    void Awake(){

        //找到警报灯脚本

        alarmLight = GameObject.FindWithTag(Tags.AlarmLight).GetComponent<AlarmLight>();

        mainAudio = GetComponent<AudioSource>();    //找到主背景音乐

 

        //找到警报背景音乐

        panicAudio = transform.GetChild(0).GetComponent<AudioSource>();

 

        //先找到所有喇叭对象

        GameObject[]  sirens =GameObject.FindGameObjectsWithTag(Tags.Siren);

        alarmAudios = new AudioSource[sirens.Length];  //初始化AudioSource数组

 

         //获取所有喇叭对象中的AudioSource组件

        for(inti =0;  i< sirens.Length;  i++){

          alarmAudios[i] =sirens[i].GetComponent<AudioSource>();

        }

    }

 

    void  Update(){

        //解除警报

        if(alarmPosition == normalPosition){

             alarmLight.alarmOn =false;   //关闭警报灯

 

             //渐渐关闭警报背景音乐

            panicAudio.volume =Mathf.Lerp(panicAudio.volume,0,Time.deltaTime*turnSpeed);

 

            //逐个渐渐关闭警报喇叭声音

            for(inti=0;  i <alarmAudios.Length;  i++){

               alarmAudios[i].volume = Mathf.Lerp(alarmAudios[i].volume,0,Time.deltaTime*turnSpeed);

            }

 

            //渐渐开启主背景音乐

            mainAudio.volume = Mathf.Lerp(mainAudio.volume,1,Time.deltaTime*turnSpeed);

 

        }else{    //开启警报

            alarmLight.alarmOn =true;    //开启警报灯

 

             //渐渐关闭主背景音乐

            mainAudio.volume = Mathf.Lerp(mainAudio.volume,0,Time.deltaTime*turnSpeed);

 

            //渐渐开启警报背景音乐

            panicAudio.volume = Mathf.Lerp(panicAudio.volume,1,Time.deltaTime*turnSpeed);

 

           //渐渐开启警报喇叭声音

            for(int i = 0;  i < alarmAudios.Length;  i++){

                 alarmAudios[i].voluem = Mathf.Lerp(alarmAudios[i].volume,1,Time.deltaTime*turnSpeed);

            }

       }

    }

}


###LiftDoorsTracking.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\LiftDoorsTracking.cs

using UnityEngine;

using System.Collections;

using UnityEngine.SceneManagement;

 

public  class LiftDoorTracking:MonoBehaviour{

    private float  timer;

    public float  waitTime=1f;

    public float  moveTime=2f;

    public float moveSpeed=3f;

 

    private Transform  player;

    private AudioSource liftRaise;

    private AudioSource  endGame;

 

    void Awake(){

        player = GameObject.FindWithTag(Tags.Player).transform;

        liftRaise = GetComponent<AudioSource>();

       endGame = transform.parent.GetComponent<AudioSource>();

    }

 

    void  OnTriggerStay(Collider  other){

        if(other.tag == Tags.Player){

            timer += Time.deltaTime;

        

            //到达上升时间

            if(timer > waitTime){

                //播放电梯声音

               if(!liftRaise.isPlaying){

                   liftRaise.Play();

                }

 

               //播放结束游戏声音

                if(!endGame.isPlaying){

                   endGame.Play();

                }

 

                //电梯上升

                transform.root.position += Vector3.up*Time.deltaTime*moveSpeed;

 

                //人物上升

                player.position +=Vector3.up*Time.deltaTime*moveSpeed;

 

                if(timer > waitTime+moveTime){

                      //TODO:重启游戏

                   SceneManager.LoadScene(“Yanlz_Demo006_Stealth”);

                }

            }

        }

    }

}


###PlayerHealth.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\PlayerHealth.cs

using UnityEngine;

using System.Collections;

using UnityEngine.SceneManagement;

 

public  class  PlayerHealth:MonoBehaviour{

    public float health =100;    //玩家血量

    public AudioClip  endGameAud;    //游戏结束声音

    private  Animator  ani;

    private  bool  isdead = false;    //玩家是否死亡

    private  bool  endGame = false;    //游戏结束

 

    void Awake(){

        ani = GetComponent<Animator>();

    }

 

    public void TakeDamage(float  damage){

        health -= damage;

    }

 

    void  Update(){

        //如果血量小于等于0,死亡

        if(health <=0&& !isdead){

            ani.SetTrigger(HashIDs.Dead);

            isdead = true;

        }else if(isdead&& !endGame){

            StartCoroutine(EndGame());    //开启结束游戏协程

            endGame = true;

        }

    }

 

    IEnumerator EndGame(){

        AudioSource.PlayClipAtPoint(endGameAud,transform.position);    //播放结束音效

        yield return new WaitForSeconds(4.4f);    //等待4.4

       SceneManager.LoadScene(“Yanlz_Demo003_Stealth”);

    }

}


###PlayerInventory.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\PlayerInventory.cs

using UnityEngine;

using System.Collections;

 

public  class PlayerInventory:MonoBehaviour{

    public boolhasKey=false;    //玩家是否拥有钥匙

}


###PlayerMovement.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\PlayerMovement.cs

using UnityEngine;

using System.Collections;

 

//立钻哥哥:玩家控制脚本

public class PlayerMovement:MonoBehaviour{

    public float turnSpeed=10;    //转身速度

    private float hor,ver;    //操纵键变量

    private  bool  sneak=false;

    private  Animator  ani;    //动画组件

    private  AudioSource  aud;    //声音组件

    private PlayerHealth  playerHealth;

 

    void  Awake(){

        ani = GetComponent<Animator>();

        aud = GetComponent<AudioSource>();

        playerHealth = GetComponent<PlayerHealth>();

    }

 

    void  Update(){

        if(playerHealth.health>0){

            //获取用户的按键情况

            hor = Input.GetAxis(“Horizontal”);

            ver = Input.GetAxis(“Vertical”);

        }else{

            hor = 0;

            ver = 0;

        }

 

        if(Input.GetKey(KeyCode.LeftShift)){

            sneak = true;

        }else{

            sneak = false;

        }

 

        //设置潜行参数

        ani.SetBool(HashIDs.Sneak, sneak);

 

        //如果用户按下了方向键

        if(hor!=0 || ver!= 0){

            //动画参数Speed渐变到5.5(奔跑动画)

            ani.SetFloat(HashIDs.Speed,5.5f,0.1f, Time.deltaTime);

            TurnDir(hor, ver);    //玩家转向

        }else{

            ani.SetFloat(HashIDs.Speed,0);    //立刻停下来

        }

 

        FootSteps();    //执行脚本声控制

    }

 

    //玩家转向

    void TurnDir(float hor,  float ver){

        Vector3 dir = new Vector3(hor,0,ver);    //拿到方向向量

 

        //将方向向量转换成四元数(参考Y轴)

        Quaternion qua  = Quaternion.LookRotation(dir);

 

        //玩家转向到该方向

        transform.rotation =Quaternion.Lerp(transform.rotation,qua,Time.deltaTime*turnSpeed);

    }

 

    void FootSteps(){

        //如果当前玩家正在播放Locomotion正常行走的动画

        if(ani.GetCurrentAnimatorStateInfo(0).shortNameHash == HashIDs.LocomotionState){

            //如果脚步声没有播放

            if(!aud.isPlaying){

               aud.Play();    //播放

             }

        }else{

            aud.Stop();    //停止播放脚步声

        }

    }

}


###SyncDoor.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\SyncDoor.cs

using UnityEngine;

using System.Collections;

 

public class  SyncDoor:MonoBehaviour{

    public Transform  outterleft;

    public Transform  outterright;

    private  Transform  innerleft;

    private  Transform innerright;

 

    void  Awake(){

        innerleft = transform.GetChild(0);

        innerright = transform.GetChild(1);

    }

 

    void  Update(){

        //左右里门同步左右外门

        innerleft.localPosition = new Vector3(innerleft.localPosition.x,innerleft.localPosition.y,outterleft.localPosition.z);

        innerright.localPosition = new Vector3(innerright.localPosition.x,innerright.localPosition.y,outterright.localPosition.z);

    }

}


###Tags.cs

D:\zz_DemoPro()-\小案例006、秘密行动Demo\Demo006_StealthActionDemo\Assets\Scripts\Tags.cs

using UnityEngine;

using System.Collections;

 

//立钻哥哥:标签管理

public class  Tags{

    public const  stringAlarmLight=“AlarmLight”;

    public  const  stringSiren= “Siren”;

    public const stringPlayer=“Player”;

    public  const  string  GameController=“GameController”;

    public  const  string  Enemy=“Enemy”;

}




#小案例007A_Star

++小案例007A_Star

++++FindPath.cs

++++GridMap.cs

++++Node.cs




###FindPath.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  FindPath : MonoBehaviour{

    private GridMap _grid;   //整张地图

    public Transform startPoint, endPoint;

 

    private void  Start(){

        _grid = GameObject.FindObjectOfType<GridMap>();

    }

 

    private void  Update(){

        FindingPath(startPoint.position,  endPoint.position);

    }

 

    //立钻哥哥:核心算法:生成路径

    private void FindingPath(Vector3  startPos,Vector3 EndPos){

        //获取起点和终点的格子

        Node startNode = _grid.GetNodeFromPosition(StartPos);

        Node endNode = _grid.GetNodeFromPosition(EndPos);

 

        //创建开启列表和关闭列表

        List<Node> openSet =new List<Node>();

        HashSet<Node>closeSet =new HashSet<Node>();

 

        openSet.Add(startNode);

        while(openSet.Count>0){

             Node currentNode =openSet[0];    //从开启列表中随便取出一个节点

        

             //取最小的节点

             for(int i=0;  i < openSet.Count;  i++){

                if(openSet[i].fCost < currentNode.fCost){

                   currentNode = openSet[i];

                }

              }

 

             //从开启列表移除,加入关闭列表

            openSet.Remove(currentNode);

            closeSet.Add(currentNode);

 

            //找到终点

            if(currentNode == endNode){

               GeneratePath(startNode, endNode);    //生成一条路径

                return;

            }

 

            foreach(var node in _grid.GetNeibourhood(currentode)){

               if(!node._canWalk||closeSet.Contains(node)){

               continue;

            }

 

            //计算与相邻格子的距离

             int  newCost = currentNode.gCost + GetDistance(currentNode,node);

             if(newCost <node.gCost || !openSet.Contains(node)){

                  node.gCost =newCost;

                   node.hCost = GetDistance(node,endNode);

                   node.parent = currentNode;

 

                   if(!openSet.Contains(node)){

                      openSet.Add(node);

                    }

                }

            }

        }

    }

 

    //计算两点间的距离

    int GetDistance(Node a, Nodeb){

        int cntX= Mathf.Abs(a._gridX-b._gridX);

        int cntY =Mathf.Abs(a._gridY-b._gridY);

 

        if(cntX>cntY){

            return 14*cntY+10* (cntX-cntY);

        }else{

            return 14*cntX+10* (cntY-cntX);

        }

    }

 

    //生成最终路径

    private void GeneratePath(Node startNode,Node  endNode){

        List<Nodepath =new List<Node>();

        Node temp = endNode;

 

        while(temp !=startNode){

            path.Add(temp);

            temp = temp.parent;

        }

 

        path.Reverse();

        _grid.path=path;

    }

}


###GridMap.cs

D:\yanlz_DemoPro()-\小案例007AStar\Assets\GridMap.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  GridMap:MonoBehaviour{

    private Node[,]  grid;    //存放所有格子的容器

 

    [Tooltip(地图的尺寸)]

    public Vector2 gridSize;

 

    [Tooltip(每个格子的半径)]

    public float  nodeRadius;

 

    //直径

    private float nodeDiamenter{

        get{    return  nodeRadius*2;  }

    }

 

    [Tooltip(障碍物所在的层)]

    public  LayerMask ObstacleLayer;

 

    private int  gridCntX,gridCntY;    //地图上横纵格子数量

    public List<Node>path = new List<Node>();    //最终路径

 

    private void Start(){

        gridCntX = Mathf.RoundToInt(gridSize.x /nodeDiameter);

        gridCntY = Mathf.RoundToInt(gridSize.y /nodeDiameter);

        grid = newNode[gridCntX,gridCntY];

 

        CreateGrid();

    }

 

    //立钻哥哥:创建节点

    private void CreateGrid(){

        Vector3 startPoint = transform.position-gridSize.x /2 *Vector3.right-Vector3.forward*gridSize.y /2;

 

        for(int i=0;  i < gridCntX;  i++){

            for(intj =0;  j < gridCntY;  j++){

                //每个格子的世界坐标

               Vector3  worldPoint = startPoint+ Vector3.right* (i *nodeDiameter+nodeRadius) +Vector3.forward* (j *nodeDiameter+nodeRadius);

            

                //格子上是否有障碍物

               bool  canWalk = !Physics.CheckSphere(wordPoint,nodeRadius,ObstacleLayer);

               grid[i,j] = new Node(canWalk,worldPoint,i,j);

            }

        }

    }

 

    //立钻哥哥:Unity回调

   private void  OnDrawGizmos(){

        if(Application.isPlaying==false){

            return;

        }

 

        if(gird ==null){

            return;

        }

 

        foreach(var node in grid){

            Gizmos.color = node._canWalk?Color.gray:Color.red;    //指定颜色

    

            //绘制图形

            Gizmos.DrawCube(node._wordPos, (nodeDiameter -nodeDiameter*0.1f) *Vector3.one);

        }

 

        if(path !=null){

            foreach(var node  in path){

               Gizmos.color = Color.green;

               Gizmos.DrawCube(node._wordPos, (nodeDiameter -nodeDiameter*0.1f) *Vector3.one);

            }

        }

    }

 

    //根据世界位置,得到Node

    public Node GetNodeFromPosition(Vector3 position){

        float percentX = (position.x +gridSize.x /2) / gridSize.x;

        float percentY = (position.z +gridSize.y /2) / gridSize.y;

 

        percentX = Mathf.Clamp01(percentX);

        percentY = Mathf.Clamp01(percentY);

 

        int x = Mathf.RoundToInt((gridCntX-1) *percentX);

        int y = Mathf.RoundToInt((gridCntY-1) *percentY);

 

        return grid[x,y];

    }

 

    //获取一个格子周围的8个格子

    public List<NodeGetNeibourhood(Node  node){

        List<Node>  neibourhood=  new List<Node>();

    

        for(inti = -1;  i <=1;  i++){

            for(int j = -1;  j <= 1;  j++){

               if(i ==0&& j==0){

                   continue;

                }

 

                int tempX= node._gridX+i;

                int  tempY= node._gridY+j;

                if(tempX < gridCntX && tempX > 0 && tempY> 0 &&tempY<gridCntY){

                   neibourhood.Add(grid[tempX,tempY]);

                }

            }

        }

 

        return  neibourhood;

    }

}


###Node.cs

D:\yanlz_DemoPro()-\小案例007AStar\Assets\Node.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

//立钻哥哥:格子数据结构

//Node: 一个小格子

//GridMap: 整张地图

//FindPath: 根据A*算法,生成的路径

public class Node{

    public int  gCost;

    public int  hCost;

 

    public int fCost{

        get{    return  gCost+hCost;    }

    }

 

    public Node  parent;    //指向父格子的指针

    public int  _gridX,_gridY;    //格子序号

    public  bool _canWalk;    //格子上方是否有障碍物

    public  Vector3 _worldPos;    //格子所在的世界坐标

 

    public Node(bool  Canwalk,  Vector3  position,  int  x,  int  y){

        _canWalk = Canwalk;

        _worldPos = position;

        _gridX = x;

        _gridY = y;

    }

}





#小案例008、血条LiftBar跟随

++小案例008、血条LiftBar跟随

++++FaceToCamera.cs

++++HeadHP.cs

++++HPTest.cs

++++PlayerMove.cs




###FaceToCamera.cs

D:\yanlz_DemoPro()-\小案例008、血条LiftBar跟随\Assets\FaceToCamera.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public  class  FaceToCamera :MonoBehaviour{

    private  Camera  camera;

 

    void  Start(){

        camera = Camera.main;

    }

 

    //立钻哥哥:Update is called once per frame

    void  Update(){

        Vector3 pos= camera.transform.position-transform.position;

        pos.x = pos.z = 0;

        transform.LookAt(camera.transform.position-pos);

        transform.Rotate(0,180,0);

    }

}


###HeadHP.cs

D:\yanlz_DemoPro()-\小案例008、血条LiftBar跟随\Assets\HeadHP.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public class HeadHP:MonoBehaviour{

    private  Image image;

    private int  hp=150;

    private int maxhp;

 

    void  Start(){

        image = GetComponent<Image>();

        maxhp = hp;

    }

 

    void Update(){

        if(Input.GetKeyDown(KeyCode.Space)){

            hp -= 10;

            image.fillAmout = (float)hp/maxhp;

        }

    }

}


###HPTest.cs

D:\yanlz_DemoPro()-\小案例008、血条LiftBar跟随\Assets\HPTest.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public  class  HPTest:MonoBehaviour{

    private  RectTransform  rectTrans;

    public  Transform target;

    public Vector2 offsetPos;

 

    void  Start(){

        rectTrans = GetComponent<RectTransform>();

    }

 

    void  Update(){

        Vector3   postar =target.transform.position;

        Vector2   pos=RectTransformUtility.WorldToScreenPoint(Camera.main,postar);

 

        rectTrans.position =pos+offsetPos;

    }

}


###PlayerMove.cs

D:\yanlz_DemoPro()-\小案例008、血条LiftBar跟随\Assets\PlayerMove.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.AI;

 

public class PlayerMove:MonoBehaviour{

    private  NavMeshAgent  nav;

 

    void  Start(){

        nav = GetComponent<NavMeshAgent>();

    }

 

    void  Update(){

        if(Input.GetMouseButtonDown(0)){

            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            Raycasthit  hit;

        

            if(Physics.Raycast(ray,  out hit)){

               nav.SetDestination(hit.point);

            }

        }

    }

}





#小案例009、见缝插针StickPin

#小案例009、见缝插针StickPin

++++GameManager.cs

++++Pin.cs

++++PinHead.cs

++++RotateSelf.cs



###GameManager.cs

D:\yanlz_DemoPro()-\小案例009、见缝插针StickPin\Assets\Scripts\GameManager.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.SceneManagement;

 

public class GameManager:MonoBehaviour{

    private  Transform  startPoint;

    private  Transform  spawnPoint;

    private Pin currentPin;

    private  bool  isGameOver=false;

    private int  score =0;

    private Camera  mainCamera;

 

    public  Text  scoreText;

    public  GameObject  pinPrefab;

    public float  speed =3;

 

    void  Start(){

        startPoint  = GameObject.Find(“StartPoint”).transform;

        spawnpoint  = GameObject.Find(“SpawnPoint”).transform;

        mainCamera = Camera.main;

 

        SpawnPin();

    }

 

    private void  Update(){

        if(isGameOver){

            return;

        }

 

        if(Input.GetMouseButtonDown(0)){

            score++;

            scoreText.text = score.ToString();

            currentPin.StartFly();

 

            SpawnPin();

        }

    }

 

    void SpawnPin(){

        currentPin = GameObject.Instantiate(pinPrefab,spawnPoint.position,pinPrefab.transform.rotation).GetComponent<Pin>();

    }

 

    public void GameOver(){

        if(isGameOver){

            return;

        }

 

        GameObject.Find(“Circle”).GetComponent<RotateSelf>().enabled = false;

 

        StartCoroutine(GameOverAnimation());

 

        isGameOver = true;

    }

 

    IEnumerator GameOverAnimation(){

        while(true){

            mainCamera.backgroundColor = Color.Lerp(mainCamera.backgroundColor,Color.red,  speed* Time.deltaTime);

            mainCamera.orthographicSize=Mathf.Lerp(mainCamera.orthographicSize,  4,  speed*Time.deltaTime);

        

            if(Mathf.Abs(mainCamera.orthographicSize-4) <0.01f){

               break;

            }

 

            yield return  0;

        }

 

        yield return new WaitForSeconds(0.2f);

 

        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

    }

}



###Pin.cs

D:\yanlz_DemoPro()-\小案例009、见缝插针StickPin\Assets\Scripts\Pin.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class Pin:MonoBehaviour{

    public float  speed= 5;

    private bool  isFly =false;

    private bool  isReach =false;

 

    private Transform  startPoint;

    private  Vector3 targetCirclePos;

    private  Transform  circle;

 

    void  Start(){

        startPoint = GameObject.Find(“StartPoint”).transform;

 

        //circle = GameObject.Find(Circle).transform;

        circle = GameObject.FindGameObjectWithTag(“Circle”).transform;

        targetCirclePos = circle.position;

        targetCirclePos.y -= 1.55f;

    }

 

    void  Update(){

        if(isFly ==false){

            if(isReach==false){

               transform.position = Vector3.MoveTowards(transform.position,  startPoint.position,  speed*Time.deltaTime);

                if(Vector3.Distance(transform.position,  startPoint.position) <0.05f){

                   transform.positiontargetCirclePos;

                   transform.parent =circle;

                   isFly =false;

                }

            }

        }

    }

 

    public void StartFly(){

            isFly = true;

            isReach = true;

    }

}


###PinHead.cs

D:\yanlz_DemoPro()-\小案例009、见缝插针StickPin\Assets\Scripts\PinHead.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public class  PinHead:MonoBehaviour{

    private void  OnTriggerEnter2D(Collider2D  collision){

        if(collision.tag ==“PinHead”){

            GameObject.Find(“GameManger”).GetComponent<GameManager>().GameOver();

        }

    }

}


###RotateSelf.cs

D:\yanlz_DemoPro()-\小案例009、见缝插针StickPin\Assets\Scripts\RotateSelf.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

public  class  RotateSelf:MonoBehaviour{

    public float  speed=90;

 

    void  Update(){

        transform.Rotate(new Vector3(0,0, -speed* Time.deltaTime));

    }

}




#小案例010UnityNetDemo

#小案例010UnityNetDemo

++++Player.cs



###Player.cs

D:\yanlz_DemoPro()-\小案例010UnityNetDemo\Assets\Player.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.Networking;

 

public  class Player :NetworkBehaviour{

    public float  rotSpeed=150f;

    public float  movSpeed= 3.0f;

    private float  hor,ver;

    publicGameObject  bulletPrefab;

    publicTransform  bulletSpawn;

 

    voidUpdate(){

        if(!isLocalPlayer){

            return;

        }

 

        PlayerMove();

 

        if(Input.GetKeyDown(KeyCode.Space)){

            CmdFire();

        }

    }

 

    [Command]

    void CmdFire(){

        GameObject bullect =Instantiate<GameObject>(bulletPrefab,bulletSpawn.position,bullectSpawn.rotation);

        bullect.GetComponent<Rigidbody>().velocity = bullet.transform.forward*6;

        NetworkServer.Spawn(bullect);

        Destroy(bullet,2f);

    }

 

    void PlayerMove(){

        hor = Input.GetAxis(“Horizontal”) * Time.deltaTime*rotSpeed;

        ver = Input.GetAxis(“Vertical”) * Time.deltaTime*movSpeed;

        transform.Rotate(0, hor, 0);

        transform.Translate(0,0, ver);

    }

 

    public override  void  OnStartLocalPlayer(){

        GetComponent<MeshRenderer>().material.color= Color.green;

    }

}




#小案例011SocketFileRecv

#小案例011SocketFileRecv

++++Server\Program.cs

++++Client\Program.cs


###Server\Program.cs

D:\yanlz_DemoPro()-\小案例011socketFileRecv\Server\ConsoleApp1\Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Net.Sockets;

using System.Text;

using System.Threading;

using System.Threading.Tasks;

 

namespace Server{

    class Program{

        static void Main(string[]  args){

            Myserver server = newMyserver();

            server.Start();

        }

    }

 

    class Myserver{

        Socket serverSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

        IPEndPoint point = new IPEndPoint(IPAddress.Any,12345);

 

        public void Start(){

            serverSocket.Bind(point);

            serverSocket.Listen(10);

            Console.WriteLine(立钻哥哥Print:服务器启动成功);

 

            Thread acceptThread = new Thread(Accept);

            acceptThread.IsBackground =true;

            acceptThread.Start();

 

            Console.ReadKey();

        }

 

        void Accept(){

            Socket client = serverSocket.Accept();

            IPEndPoint point = client.RemoteEndPointas IPEndPoint;

            Console.WriteLine(point.Address +[ + point.Port +]连接成功);

 

            Thread receiveThread = new Thread(Receive);

            receiveThread.IsBackground= true;

            receiveThread.Start(client);

 

            Accept();

        }

 

        public void Receive(objectobj){

            Socket client = objas Socket;

            IPEndPoint point= client.RemoteEndPointas IPEndPoint;

            byte[]msg =newbyte[1024];

            int length= client.Receive(msg);

            Console.WriteLine(point.Address +[ + point.Port +] + Encoding.UTF8.GetString(msg, 0, length));

    

            Receive(client);

        }

    }

}


###Client\Program.cs

D:\yanlz_DemoPro()-\小案例011socketFileRecv\Client\ConsoleApp2\Program.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net.Sockets;

using System.Text;

using System.Threading.Tasks;

 

namespace  Client{

    class  Program{

        static void Main(string[]  args){

            MyClient client = newMyClient();

            client.Connect(“127.0.0.1”,12345);

            Console.WriteLine(立钻哥哥Print:请输入内容);

       

            string msg = Console.ReadLine();

            while(msg!= “q”){

               client.Send(msg);

               msg =Console.ReadLine();

            }

        }

 

        class MyClient{

            Socket clientSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

    

            public void Connect(stringip,int port){

               clientSocket.Connect(ip,port);

                Console.WriteLine(立钻哥哥Print:连接成功);

            }

 

            public void  Send(string msg){

               clientSocket.Send(Encoding.UTF8.GetBytes(msg));

            }

        }

    }

}




#小案例012、切水果CutFruitDemo

#小案例012、切水果CutFruitDemo

++++MouseControl.cs

++++DestroyOnTime.cs

++++ObjectControl.cs

++++Spawner.cs

++++UIOver.cs

++++UIScore.cs

++++UIStart.cs




###MouseControl.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\MouseControl.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public  class  MouseControl:MonoBehaviour{

    LineRenderer  lineRenderer;

    Vector3[]  positions=new Vector3[10];

    bool  firstMouse;

    bool  MouseDown;

 

    Vector3  head;

    Vector3  last;

 

    int posCount;

 

    private voidStart(){

        lineRenderer = GetComponent<LineRenderer>();

    }

 

    private void  Update(){

        if(Input.GetMouseButtonDown(0)){

            firstMouse = true;

            MouseDown = true;

        }

 

        if(Input.GetMouseButtonUp(0)){

            MouseDown = false;

        }

 

        OnDrawLine();

        firstMouse=false;

    }

 

    private void OnDrawLine(){

        if(firstMouse){

            posCount = 0;

            head = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePositon.x,Input.mousePosition.y,12.9f));

            last = head;

        }

 

        if(MouseDown){

            head = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x,Input.mousePosition.y,12.9f));

            if(Vector3.Distance(head,last) > 0.01f){

               SavePosition(head);

               posCount++;

               OnRayCast(head);

            }

            last=head;

        }else{

           positions = new Vector3[10];

        }

 

        ChangePositions(positions);

    }

 

    void SavePosition(Vector3 pos){

        if(posCount <= 9){

            for(inti =posCount;  i <=9;  i++){

               positions[i] =pos;

            }

        }else{

            for(int i =0;  i<9;  i++){

               positions[i] =positions[i +1];

               positions[9] =pos;

            }

        }

    }

 

    void ChangePositions(Vector3[ ]  positions){

        linerRenderer.SetPositions(positions);

    }

 

    void OnRayCast(){

        Vector3 screenPosition = Camera.main.WorldToScreenPoint(pos);

        Ray ray = Camera.main.ScreenPointToRay(screenPosition);

        RaycastHit[]hits =Physics.RaycastAll(ray);

 

        for(int i =0;  i <hits.Length;  i++){

            hits[i].collider.gameObject.SendMessage(“OnCut”,SendMessageOptions.DontRquireReceiver);

        }

    }

}


###DestroyOnTime.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\DestroyOnTime.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//立钻哥哥:按照时间销毁

public class  DestroyOnTime:MonoBehaviour{

    public float  desTime=2f;

 

    void  Start(){

        Invoke(“Dead”, desTime);

    }

 

    void Dead(){

        Destroy(gameObject);

    }

}


###ObjectControl.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\ObjectControl.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//立钻哥哥:物体控制脚本

public  class  ObjectControl:MonoBehaviour{

    public GameObject  halfFruit;  //一半的水果

    public  GameObject  Splash;

    public  GameObject SplashFlat;

    public GameObject  Firework;

    private bool  dead=false;

    public  AudioClip  ac;

 

    //被切割的时候调用

    public void OnCut(){

        //防止重复调用

        if(dead){

            return;

        }

 

        if(gameObject.name.Contains(“Bomb”)){

            //生成特效

            Instantiate(Firework,transform.position,Quaternion.identity)

            UIScore.Instance.Remove(20);    //如果是炸弹,就需要扣分

        }else{

            //先生成被切割的水果

            for(inti = 0;  i <2;  i++){

               GameObject  go= Instantiate<GameObject>(halfFruit,transform.position,Random.rotation);

               go.GetComponent<Rigidbody>().AddForce(Random.onUnitSphere*5f,ForceMode.Impulse);

            }

 

             //生成特效

            Instantiate(Splash,transform.position,Quaternion.identity);

            Instantiate(SplashFlat,transform.position,Quaternion.identity);

            UIScore.Instance.Add(10); //如果是水果,就加分

        }

 

        AudioSource.PlayClipAtPoint(ac,transform.position);

 

        Destroy(gameObject); //销毁自身

        dead = true;

    }

}


###Spawner.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\Spawner.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//立钻哥哥:用来产生水果、炸弹等(也让它能控制销毁)

public  class  Spawner:MonoBehaviour{

    [Header(水果的预设)]

    public GameObject[]  Fruits;

 

    [Header(炸弹的预设)]

    public GameObject  Bomb;

 

    public AudioSource  audioSource;    //播放声音的组件

    float  spawnTime = 3f;    //产生时间

    bool isPlaying = true;    //是否在玩游戏

 

    void  Update(){

        if(!isPlaying){

            return;

        }

 

        spawnTime-= Time.deltaTime;

 

        if(0 >spawnTime){

            //到时间了就开始产生水果

            int fruitCount= Random.Range(1,5);    

            for(inti=0;  i <fruitCount;  i++){

               onSpawn(true);

            }

 

            //随机产生炸弹

            int bombNum = Random.Range(0,100);

            if(bombNum>10){

               onSpawn(false);

            }

 

            spawnTime=3f;

        }

    }

 

    private  int  tmpZ=0;    //临时存储当前水果的z坐标

 

    //产生水果和炸弹

    //param isFruit:是否是水果

    private void onSpawn(bool  isFruit){

        this.audioSource.Play();    //播放音乐

 

        //x范围:-8.4~8.4

        //y范围:transform.pos.y

        //得知坐标范围

        float x =Random.Range(-8.4f, 8.4f);

        float y = transform.position.y;

        float z =tmpZ;

 

        //tmpZ -= 2;

        tmpZ = tmpZ-2;    //使水果不在一个平面上

        if(tmpZ<= -10){

            tmpZ = 0;

        }

 

        //实例化水果

        int fruitIndex =Random.Range(0, Fruits.Length);

        GameObject  go;

        if(isFruit){

            go = Instantiate<GameObject>(Fruits[fruitIndex],new Vector3(x,y,z),Random.rotation);

        }else{

            go = Instantiate<GameObject>(Bomb,new Vector3(x,y,z),Random.rotation)

        }

 

        //水果的速度

        Vector3  velocity  =new Vector3(-x *Random.Range(0.2f,0.8f), -Physics.gravity.y *Random.Range(1.2f,1.5f),0);

 

        //Rigidbody rigidbody = transform.GetComponent<Rigibody>();

        Rigidbody  rigidbody = go.GetComponent<Rigidbody>();

        rigidbody.velocity= velocity;

    }

 

    //有物体碰撞的时候调用

    private  void OnCollisionEnter(Collision  other){

        Destroy(other.gameObject);

    }

}


###UIOver.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\UIOver.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.Events;

 

public  class UIOver :MonoBehaviour{

    public  UnityEvent  events;

 

    public void OnClick(){

        UnityEngine.SceneManagement.SceneManager.LoadScene(0);

    }

}


###UIScore.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\UIScore.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public  class  UIScore:MonoBehaviour{

    public  static  UIScore Instance=null;    //立钻哥哥:单例对象

 

    void  Awake(){

        Instance = this;

    }

 

    [SerializeField]

    private  Text txtScore;

    private int score = 0;    //当前多少分

 

    //加分

    public void Add(int  score){

        this.score +=  score;

        textScore.textthis.score.ToString();

    }

 

    //扣分

    public void Remove(int  score){

        this.score -=  score;

 

        //如果分数小于0,那么游戏结束

        if(this.score <= 0){

            UnityEngine.SceneManagement.SceneManager.LoadScene(“over”);

            return;

        }

 

        textScore.text =this.score.ToString();

    }

}


###UIStart.cs

D:\yanlz_DemoPro()-\小案例012、切水果CutFruitDemo\Assets\Scripts\UIStart.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using UnityEngine.SceneManagement;

 

public  class  UIStart:MonoBehaviour{

    private  Button btnPlay;    //开始按钮

    private  Button  btnSound;    //声音按钮

    private  AudioSource audioSourceBG; //背景音乐播放器

    private  Image  imgSound;    //声音的图片

    public  Sprite[]  soundSprites;    //声音的图片

 

    void  Start(){

        getCompnents();

 

        btnPlay.onClick.AddListener(onPlayClick);

        bthSound.onClick.AddListener(onSoundClick);

    }

 

    void  OnDestroy(){

        btnPlay.onClick.RemoveListener(onPlayClick);

        btnPlay.onClick.RemoveListener(onSoundClick);

    }

 

    //寻找组件

    private void getComponents(){

        btnPlay = transform.Find(“btnPlay”).GetComponent<Button>();

        btnSound = transform.Find(“btnSound”).GetComponent<Button>();

        audioSourceBG = transform.Find(“btnSound”).GetComponent<AudioSource>();

        imgSound = transform.Find(“btnSound”).GetComponent<Image>();

    }

 

    //当开始按钮按下的点击事件

    void onPlayClick(){

        SceneManager.LoadScene(“play”,LoadSceneMode.Single);

    }

 

    //当声音按钮点击时候调用

    void onSoundClick(){

        if(audioSourceBG.isPlaying){

            //正在播放

            audioSourceBG.Pause();

            imgSound.sprite=soundSprites[1];

        }else{

            //停止播放

            audioSourceBG.Play();

            imgSound.sprite=soundSprites[0];

        }

    }

}




#小案例013、吃鸡_友军方位UV

#小案例013、吃鸡_友军方位UV

++++CoordScript.cs

++++FriendMoveScript.cs

++++CameraScript.cs



###CoordScript.cs

D:\yanlz_DemoPro()-\小案例013、吃鸡_友军方位UV\FriendCoordTest\Assets\CoordScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

using UnityEngine.UI;

 

public  class CoordScript:MonoBehaviour{

    RawImage  rawImage;

    public Transform  friendTrans;    //友军

    public  Transform  friendImg;    //友军Image

    float  width;

 

    private void  Start(){

        rawImage = GetComponent<RawImage>();

        width = transform.GetComponent<RectTransform>().rect.width;

    }

 

    private void  Update(){

        Rect  tmpRect  = new Rect(GetY(Camera.main.transform.eulerAngles.y),0.38f,1,1);

        rawImage.uvRect =tmpRect;

 

        //相机的投影前方

        Vector3 cameraForward =new Vector3(Camera.main.transform.forward.x,0,Camera.main.transform.forward.z);

 

        //计算与友军的夹角

        Vector3 dir = friendTrans.position-Camera.main.transform.position;

        dir = new Vector3(dir.x, 0, dir.z);

        float angle= Vector3.Angle(cameraForward,dir);

 

        //计算友军左右

        Vector3 normal =Vector3.Cross(cameraForward,dir);

        angle = normal.y<0 ?360-angle : angle;    //计算最终夹角

        float percent =GetYY(angle);    //根据角度(0-1)的percent

        float x =percent* width - width/2;    //变换

        friendImg.transform.localPosition =new Vector3(x, -30,0);

    }

 

    private float GetY(float  x){

        return (1 /360.0f) * (x %360) + 0.5f;

    }

 

    private float GetYY(float  x){

        return ((1 /180.0f) *x /2 +0.5f) %1;

    }

}


###FriendMoveScript.cs

D:\yanlz_DemoPro()-\小案例013、吃鸡_友军方位UV\FriendCoordTest\Assets\FriendMoveScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public class  FriendMoveScript:MonoBehaviour{

    private void  Update(){

        transform.RotateAround(Vector3.zero,Vector3.up, Time.deltaTime*90f);

    }

}


###CameraScript.cs

D:\yanlz_DemoPro()-\小案例013、吃鸡_友军方位UV\FriendCoordTest\Assets\Scripts\Application\CameraScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System;

 

public class  CameraScript:MonoBehaviour{

    public Transform  y_Axis;

    public Transform  x_Axis;

    public Transform  z_Axis;

    public Transform  zoom_Axis;

    public Transform  player;

 

    float hor,ver,scrollWheel;

    public float  roSpeed=180;

    public float  scSpeed=5f;

    float  upLimitAngle=60f;

    float downLimitAngle=0;

 

    public  bool followFlag=true;

    float x = 0;

    floatsc= 8,minDis= 1,maxDis=12;

 

    void  LateUpdate(){

        hor = Input.GetAxis(“Mouse X”);

        ver = Input.GetAxis(“Mouse Y”);

        scrollWheel = Input.GetAxis(“Mouse ScrollWheel”);

 

        //水平旋转

        if(hor != 0){

            y_Axis.Rotate(Vector3.up*roSpeed* hor *Time.deltaTime);

        }

 

        //垂直旋转

        if(ver!= 0){

            x -= ver*Time.deltaTime*roSpeed;

            x = Mathf.Clamp(x, -downLimitAngle,upLimitAngle);

            Quaternion q =Quaternion.identity;

            q = Quaternion.Euler(new Vector3(x,x_Axis.eulerAngles.y,x_Axis.eulerAngles.z));

            x_Axis.rotation=q;

        }

 

        //缩放

        if(scrollWheel  !=  0){

            sc -= scrollWheel*Time.deltaTime*scSpeed;

            zoom_Axis.transform.localPosition = new Vector3(0,0,Mathf.Clamp(-sc, -maxDis, -minDis));

        }

 

        //跟随玩家

        if(followFlag){

            y_Axis.position = player.position + Vector3.up*1.7f;

        }

 

        //控制玩家旋转

        //player.forward = new Vector3(transform.forward.x, 0, transform.forward.z);

    }

}




#小案例014、数据库背包SqliteEZ_Bag

#小案例014、数据库背包SqliteEZ_Bag

++++DataBaseController.cs

++++HeroMessage.cs

++++SqliteDataScripts.cs

++++StoreWeapon.cs

++++WeaponBox.cs




###DataBaseController.cs

D:\yanlz_DemoPro()-\小案例014SqliteEZ_Bag\Assets\DataBaseController.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using Mono.Data.Sqlite;

 

//立钻哥哥:封装数据库

public  class  DataBaseController:MonoBehaviour{

    public static  DataBaseController  instance;   //单例脚本对象

    private string  sqlitePath;    //数据库地址

    private  SqliteConnection  con;    //连接

    private  SqliteCommand  command;

    private SqliteDataReader  reader;

 

    void  Awake(){

        instance = this;

    }

 

    //连接数据库

    //param databaseName:数据库名称

    public void ConnectToSqlite(string  databaseName){

        string connectDatabaseName  = databaseName;    //获取数据库名称

    

        //判断数据库名称中是否包含.sqlite

        if(!connectDatabaseName.Contains(“.sqlite”)){

            connectDatabaseName +=“.sqlite”;    //如果不包含就添加

        }

 

        //拼接数据库连接路径

        sqlitePath =“Data Source=”  +Application.streamingAssetsPath+“/” +connectDatabaseName;

        con = new SqliteConnection(sqlitePath);    //实例化数据库连接对象

        command = con.CreateCommand();    //创建数据库指令对象

        try{

            con.Open();    //打开数据库

            print(立钻哥哥Print:数据库打开成功);

        }catch(SqliteException  ex){

            //抛出异常

            Debug.Log(立钻哥哥Print:----异常: + ex);    

        }

    }

 

    //关闭数据库

    public void CloseSqliteConnection(){

        try{

            //如果连接对象不为空

            if(con != null){

               con.Close();    //关闭数据库

            }

        }catch(SqliteExceptionex){

            Debug.Log(---- + exsss);

        }

    }

 

    //查询属性信息

    //param isHero:查询的是否是人物的属性

    //param name:人物名称或者装备名称

    public float[]SelectHeroMsg(bool isHero,string  name){

        try{

            float[]  result=newfloat[4];    //result:用于存储结果

            string selectQuery;    //查询

        

            //如果查询的是人物的属性

            if(isHero){

               selectQuery =“select AD,AP,AR,MP from hero where HeroName =‘”+name+”’”;

            }else{

               selectQuery =“select AD,AP,AR,MP from Equip where EquipName =‘”+name+”’”

            }

 

            command.CommandText =selectQuery;

 

            //执行sql语句

            reader= command.ExecuteReader();

 

            //读取第一行数据

            while(reader.Read()){

                //遍历获取的结果

                //根据字段的个数进行遍历

               for(int i =0;  i <reader.FieldCount;  i++){

                   result[i] =System.Convert.ToSingle(reader.GetValue(i));

                }

            }

            reader.Close();    //关闭连接

 

            return  result;    //返回结果

        }catch(SqliteException ex){

            Debug.Log(立钻哥哥Print:出错了~~~ + ex);

            return null;

        }

    }

 

    //添加或者移除装备

    public float[] AddOrRemoveProperty(boolisAdd,  float[] heroProperty,  float[]  equipProperty){

        try{

            if(heroProperty.Length==4 &&equipProperty.Length==4){

               float[]  result =new float[4];    //创建结果数组,保存结果

            

                //如果是添加装备

               if(isAdd){

                    //遍历添加赋值

                   for(int i =0;  i <result.Length;  i++){

                       result[i] =heroProperty[i] +equipProperty[i];

                    }

                }else{

                   //遍历移除赋值

                   for(inti =0;  i<result.Length;  i++){

                       result[i] =heroProperty[i] -equipProperty[i];

                    }

                }

 

                return result;    //将结果返回

            }else{

                Debug.Log(立钻哥哥Print:出错了,属性个数不匹配);

               return  null;

            }

        }catch(SqliteException  ex){

            Debug.Log(----异常: + ex);

            return null;

        }

    }

 

    //更新数据库中英雄的属性信息

    //param newHeroProperty:新的人物属性信息

    //param heroName:人物名称

    public void UpdateHeroProperty(float[] newHeroProperty,  string  heroName){

        try{

            //更新人物属性信息sql语句

            string updateQuery =“update hero set ad=” + newHeroProperty[0]

                +“,ap=” +newHeroProperty[1]

                +“,ar=” +newHeroProperty[2]

                +“,mp” +newHeroProperty[3]

                +“ where heroname=’”+heroName+”’”

 

            command.CommandText = updateQuery;    //赋值给指令对象

            command.ExecuteNonQuery();    //执行sql语句:增删改操作

        }catch(SqliteException  ex){

            Debug.Log(----出错了: + ex);

        }

    }

 

    //直接通过SQL语句去查询一个结果

    //returns:查询到的单个数据

    //param querySQL语句

    public  object  SelectSingle(string  query){

       try{

            command.CommandText =query;    //赋值SQL语句

            object obj =command.ExecuteScalar();    //执行查询语句

            return obj;    //返回结果

        }catch(SqliteExceptionex){

            Debug.Log(立钻哥哥Print: ----异常: + ex);

            return null;

        }

    }

 

    //查询更多数据

    //returns:数据结果

    //param query: SQL语句

    public List<ArrayList>  SelectMore(string query){

        try{

            List<ArrayList> result =new List<ArrayList>();    //创建结果数组

 

            command.CommandText= query;    //赋值SQL语句

            reader = command.ExecuteReader();    //执行

            while(reader.Read()){

               ArrayList  temp =new ArrayList();    //实例化临时集合

               for(int i =0; i <reader.FieldCount;  i++){

                   temp.Add(reader.GetValue(i));    //将结果添加到集合中

                }

                result.Add(temp);    //将临时集合添加到泛型集合(result)中

            }

 

            return  result;    //返回最终结果

 

        }catch(SqliteException  ex){

            Debug.Log(立钻哥哥Print:异常: + ex);

            return null;

        }

    }

}


###HeroMessage.cs

D:\yanlz_DemoPro()-\小案例014SqliteEZ_Bag\Assets\HeroMessage.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

//立钻哥哥:展示人物基础属性

public class  HeroMessage:MonoBehaviour{

    private  Text uiText;

 

    void  Awake(){

        uiText = transfrom.GetChild(0).GetComponent<Text>();

    }

 

    //更新人物UI的信息

    //parma msg:人物信息数组

    public void UpdateUIMessage(float[]  msg){

        //UIText赋值

        uiText.text  = 攻击力 +msg[0] +“\n” +

            法强: +msg[1] +“\n” +

            护甲: +msg[2] +“\n” +

            魔抗 +msg[3];

    }

 

    void  Start(){

        DataBaseController.instance.ConnectToSqlite(“LOL”);    //连接数据库

 

        //查询数据

        float[]  heroMsg= DataBaseController.instance.SelectHeroMsg(true, “EZ”);

        UpdateUIMessage(heroMsg);    //展示

 

        DataBaseController.instance.CloseSqliteConnection();    //关闭数据库

    }

}


###SqliteDataScripts.cs

D:\yanlz_DemoPro()-\小案例014SqliteEZ_Bag\Assets\SqliteDataScript.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using System.Data;

using Mono.Data.Sqlite;

 

public class  SqliteDataScript:MonoBehaviour{

    private string path;    //指定路径

 

    void  Start(){

        path = Application.dataPath +“/weapon.sqlite”;    //1、数据存储的路径

    

        //2、创建数据库连接(Data Source:数据源)

        SqliteConnection connection =new SqliteConnection(“Data Source=” +path);

        connection.Open();    //3、打开数据库

 

        //4、创建指令对象(真正执行sql语句)

        SqliteCommand command =connection.CreateCommand();    

 

        //5、将sql语句设置给指令对象

        //string InsertStr =insert into hero values(立钻哥哥,10,8,100);    //插入

        //string InsertStr =insert into hero values(亦菲妹妹,10,8,100);

        //string InsertStr =insert into hero(heroname,ap,ad,level)values(大哥哥,10,8,100);

        //string DeleStr =delete from hero where level <5;    //删除

        //string UpdateStr =update hero set AP=1000 where rowid=2;    //修改

 

        string SleStr =“select * from hero”;    //查询

        command.CommandText =SleStr;

 

        //6、让指令对象去执行sql语句

        //ExecuteNonQuery:只作为增,删,改操作,不做查询

        command.ExecuteNonQuery();   

 

        //查询方法1ExecuteScalar

        //command.ExecuteScalar();    //返回所有结果中的第一个查询到的值

    

        //查询方法2ExecuteReader

        //SqliteDataReader:查询到的所有值都会存储到SqliteDataReader

        SqliteDataReader reader= command.ExecuteReader();

 

        //Read: 处理结果集(只要执行一次就会读取结果中的一行数据)

        while(reader.Read()){

            string name1 =reader.GetString(0);    //取出字段值

            int ap1= reader.GetInt16(1);

            int ad1 =reader.GetInt16(2);

            int level1 =reader.GetInt16(3);

        

            print(string.Format(name:{0},ap{1},ad{2},level:{3},name1,ap1,ad1,level1));

        }

 

        connection.Close();    //7、关闭数据库

    }

}


###StoreWeapon.cs

D:\yanlz_DemoPro()-\小案例014SqliteEZ_Bag\Assets\StoreWeapon.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public  class StoreWeapon:MonoBehaviour{

    private  WeaponBox box;

    private  HeroMessage  msg;

 

    void  Start(){

        box = GameObject.FindWithTag(“WeaponB”).GetComponent<WeaponBox>();

        msg = GameObject.FindWithTag(“HeroMsg”).GetComponent<HeroMessage>();

    }

 

    //立钻哥哥:添加装备的按钮

    //param equip:装备对象

    public void OnAddEquipButtonClick(GameObject  equip){

        int index= box.CanAddEquip();    //查看装备栏中能否添加装备

    

        //index != -1证明可以添加装备

        if(index!= -1){

            //拿到装备图片

            Sprite equipImage = equip.GetComponent<Image>().sprite;    

 

            //将装备图片放置到装备栏中

            box.transform.GetChild(index).GetComponent<Image>().sprite = equipImage;

        

            string equipName = equip.name;    //获取装备名称

    

            //通过数据库查询到指定装备数据

            DataBaseController.instance.ConnectToSqlite(“LOL”);    //打开数据库

        

            //查询并获得装备属性

            float[]  equipProperty = DataBaseController.instance.SelectHeroMsg(false,equipName);

 

            //拿到人物属性

            float[]  heroProperty =DataBaseController.instance.SelectHeroMsg(true,“EZ”);

      

            //生成新的人物属性

            float[]  newHeroProperty = DataBaseController.instance.AddOrRemoveProperty(true,heroProperty,equipProperty);

 

            //将新的人物属性同步到数据库中

            DataBaseController.instance.UpdateHeroProperty(newHeroProperty,“EZ”);

 

            msg.UpdateUIMessage(newHeroProperty);    //同步UI

 

            DataBaseController.instance.closeSqliteConnection();    //关闭数据库

 

            //将当前装备栏中的装备名称,存储到PlayerPrefs

            PlayerPrefs.SetString(“Weapon” +index,equip.name);

        }

    }

}


###WeaponBox.cs

D:\yanlz_DemoPro()-\小案例014SqliteEZ_Bag\Assets\WeaponBox.cs

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

public  class  WeaponBox:MonoBehaviour{

    public  Sprite  defaultPicture;    //装备栏的默认图片

    private HeroMessage  msg;  

    public  Sprite[]  equipPicture;    //所有装备图片的数组

 

    void  Awake(){

        msg = GameObject.FindWithTag(“HeroMsg”).GetComponent<HeroMessage>();

    }

 

    void  Start(){

        //获得两个Weapon

        string weapon0 = PlayerPrefs.GetString(“Weapon0”);

        stirng weapon1= PlayerPrefs.GetString(“Weapon1”);

 

        if(weapon!=“Empty”){

            //遍历图片库

            foreach(Sprite  item  in  equipPicture){

                //如果图片库中的图片名称和PlayerPrefs的名称一样

               if(item.name== weapon0){

                   //将图片库中的这张图片显示到装备栏中

                   transform.GetChild(0).GetComponent<Image>().sprete=item;

                }

            }

        }

 

        if(weapon1!= “Empty”){

            //遍历图片库

            foreach(Sprite  item in  equipPicture){

               if(item.name == weapon1){

                   transform.GetChild(1).GetComponent<Image>().sprite=item;

                }

            }

        }

    }

 

    //能否添加装备

    public int CanAddEquip(){

        //获取两个装备栏中的图片名称

        string box01= transform.GetChild(0).GetComponent<Image>().sprite.name;

        string box02 = transform.GetChild(1).GetComponent<Image>().sprite.name;

        string defaultName =“InputFieldBackground”;    //装备栏默认图片的名称

    

        //如果装备栏中没有装备

        if(box01 == defaultName){

            return 0;

        }else if(box02 == defaultName){

            return 1;

        }else{

            return -1;

        }

    }

 

    //移除装备按钮

    //param equip:装备

    public void OnRemoveEquipButtonClick(GameObject  equip){

        string defaultName= “InputFieldBackground”;    //装备栏默认图片名

 

        if(equip.GetComponent<Image>().sprite.name!=defaultName){

            //获取当前装备栏的装备名称

            string equipName =equip.GetComponent<Image>().sprite.name;

 

            //将装备栏图片设置为默认图片

            equip.GetComponent<Image>().sprite = defaultPicture;

    

            DataBaseController.instance.ConnectToSqlite(“LOL”);    //打开数据库

 

            //查询数据库获取当前装备栏装备的属性

            float[]  equipProperty =DataBaseController.instance.SelectHeroMsg(false,equipName);

 

            //人物的属性减去装备属性,获取新的属性,再去刷新UI

            float[]  heroProperty= DataBaseController.instance.SelectHeroMsg(true,“EZ”);

 

            //得到一个新的属性

            float[]  newHeroProperty =DataBaseController.instance.AddOrRemoveProperty(false,heroProperty,equipProperty);

 

            //更新属性

            DataBaseController.instance.UpdateHeroProperty(newHeroProperty, “EZ”);

 

            msg.UpdateUIMessage(newHeroProperty);    //刷新UI

 

            DataBaseController.instance.CloseSqliteConnection();    //关闭数据库

 

            int index =0;

            for(inti =0;  i< transform.childCount;  i++){

                //如果该子对象就是自己本身

               if(equip.transform == transform.GetChild(i)){

                   index =i;    //获取位置

                    Debug.Log(equip.ToString() + | + transform.GetChild(i).ToString());

                }

            }

 

            PlayerPrefs.SetString(“Weapon” +index,“Empty”);

        }

    }

}




#小案例015Json数据存储

#小案例015Json数据存储

++++CubeItem.cs

++++CubeManager.cs

++++CubeTest.cs

++++JsonDemo.cs

++++Person.cs


###CubeItem.cs

D:\yanlz_DemoPro()-\小案例015Json数据存储\Assets\Scripts\CubeItem.cs

using UnityEngine;

using System.Collections;

 

public  class CubeItem{

    public string PosX{    get;    set;    };

    public string PosY{    get;    set;    }

    public string PosZ{    get;    set;    }

 

    public CubeItem(){

    }

 

    public CubeItem(string x,stringy,string z){

        this.PosX = x;

        this.PosY = y;

        this.PosZ = z;

    }

 

    public override  string  ToString(){

        return string.Format(“X:” +PosX+“ Y:” +PosY+“ Z:” +PosZ);

    }

}


###CubeManager.cs

D:\yanlz_DemoPro()-\小案例015Json数据存储\Assets\Scripts\CubeManager.cs

using UnityEngine;

using System.Collections;

using LitJson;

using System.Collections.Generic;

using System;

using System.IO;

 

public class  CubeManager:MonoBehaviour{

    private  Transform  m_Transform;    //父物体的Transform

    private Transform[]  allCubeTrans;    //所有子物体的Transform

    private  List<CubeItemcubeList;    //Cube对象

    private List<CubeItemposList;    //json数据里的对象

    private string  jsonPath= null;

    private GameObject  cubePrefab;

 

    void  Start(){

        m_Transform = GetComponent<Transform>();

        cubeList = new List<CubeItem>();

        posList = new List<CubeItem>();

        josnPath = Application.dataPath+“/Resources/json.txt”;

        cubePrefab = Resources.Load<GameObject>(“Prefabs/Cube”);

    }

 

    void Update(){

        if(Input.GetKeyDown(KeyCode.A)){

            ObjectToJson();

        }

 

        if(Input.GetKeyDown(KeyCode.B)){

            JsonToObject();

        }

    }

 

    //立钻哥哥:对象转Json字符串数据

    void ObjectToJson(){

        cubeList.Clear();

        allCubeTrans = m_Transform.GetComponentsInChildren<Transform>();

 

        for(int i =1;  i < allCubeTrans.Length;  i++){

            print(allCubeTrans[i].position);

 

            Vector3 pos = allCubeTrans[i].position;

            CubeItem item = new CubeItem(Math.Round(pos.x,2).ToString(),Math.Round(pos.y,2).ToString(),Math.Round(pos.z,2).ToString());

            cubeList.Add(item);

        }

 

        string  str =JsonMapper.ToJson(cubeList);

        print(str);

 

        //IO持久化json数据,把它以文本的形式存储在本地中

        StreamWriter  sw =new StreamWriter(josnPath);

        sw.Write(str);

        sw.Close();

    }

 

    //Json数据转对象

    void JsonToObject(){

        //读取json数据信息

        TextAsset  textAsset =Resource.Load<TextAsset>(“json”);

        print(textAsset.text);

 

        //把数据转化为对象

        JsonData data =JsonMapper.ToObject(textAsset.text);

        for(inti =0;  i<data.Count;  i++){

            print(data[i].ToJson());

 

            //指定对象接收数据

            CubeItem item=JsonMapper.ToObject<CubeItem>(data[i].ToJson());

            posList.Add(item);

        }

 

        for(inti =0;  i<posList.Count;  i++){

            print(posList[i].ToString());

 

            Vector3 pos=new Vector3(float.Parse(posList[i].PosX),float.Parse(posList[i].PosY),float.Parse(posList[i].PosZ));

            GameObject.Instantiate(cubePrefab,pos,Quaternion.identity,m_Transform);

        }

    }

}


###CubeTest.cs

D:\yanlz_DemoPro()-\小案例015Json数据存储\Assets\Scripts\CubeTest.cs

using UnityEngine;

using System.Collections;

using LitJson;

 

public  class  CubeTest:MonoBehaviour{

    private Transform  m_Transform;

 

    void  Start(){

        m_Transform = GetComponent<Transform>();

        Vector3 pos =m_Transform.position;

 

        string str = JsonMapper.ToJson(pos);

        print(str);

    

        //LitJosn不支持float

        CubeItem item  =  newCubeItem(pos.x,pos.y,pos.z);

        string str  =  JsonMapper.ToJson(item);

        print(str);

    }

}


###JsonDemo.cs

D:\yanlz_DemoPro()-\小案例015Json数据存储\Assets\Scripts\JsonDemo.cs

using UnityEngine;

using System.Collections;

using LitJson;

using System.Collections.Generic;

 

public  class  JsonDemo:MonoBehaviour{

    private  List<Personpersons;    //Person对象

    private  List<PersonpersonsOne;    //Json数据里的对象

 

    void  Start(){

        //单个对象转Json

        //Person p1 = new Person(aaa, 18,bbb);

        //string str = JsonMapper.ToJson(p1);

        //print(str);

 

        //Json转单个对象

        //Person p2 = JsonMapper.ToObject<Person>(str);

        //print(p2.ToString());

 

        //多个对象转Json

        persons = new List<Person>();

        Person p1 = newPerson(“aaa”,18,“bbb”);

        Person p2= newPerson(“ccc”,20,“ddd”);

        persons.Add(p1);

        persons.Add(p2);

        string str=JsonMapper.ToJson(persons);

        print(str);

 

        //Json转多个对象

        personOne = new List<Person>();

        JsonData data = JsonMapper.ToObject(str);

        for(inti = 0; i < data.Count;  i++){

            print(data.ToJson());

 

            Person item =JsonMapper.ToObject<Person>(data[i].ToJson());

            personsOne.Add(item);

        }

 

        for(int i = 0;  i < personsOne.Count;  i++){

            print(personsOne[i].ToString());

        }

    }

}


###Person.cs

D:\yanlz_DemoPro()-\小案例015Json数据存储\Assets\Scripts\Person.cs

using UnityEngine;

using System.Collections;

 

public  class  Person{

    public string Name{    get;    set;    }

    public int Age{    get;    set;    }

    public string  Address{    get;    set;    }

 

    public Person(){

    }

 

    public Person(string  name,int age,string  address){

        this.Name  = name;

        this.Age = age;

        this.Address = address;

    }

 

    public override  string  ToString(){

        return string.Format(名字: +Name+“ 年龄: +Age+“ 住址: +Address);

    }

}




#小案例016、关卡系统LevelSystem

#小案例016、关卡系统LevelSystem

++++LevelData.cs

++++LevelSelected.cs

++++MainGUI.cs


###LevelData.cs

D:\yanlz_DemoPro()-\小案例016、关卡系统LevelSystem\Assets\Script\LevelData.cs

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

 

public  class  LevelData{

    public  static int _maxLevels =PlayerPrefs.GetInt(“MaxLevels”);

    public  static int _unLockLevels = PlayerPrefs.GetInt(“UnLockedLevels”);

    static string  unLock= “unLock”;

    static string  Locked=“Locked”;

    public  static List<stringTotalLevels;

 

    public static List<stringaddLevels(){

        TotalLevels = new List<string>();

        for(int i =0;  i< PlayerPrefs.GetInt(“UnLockedLevels”);  i++){

            TotalLevels.Add(unLock);

        }

 

        for(int i =0;  i < (PlayerPrefs.GetInt(“MaxLevels”) - PlayerPrefs.GetInt(“UnLockedLevels”));i++){

            TotalLevels.Add(Locked);

        }

 

        return  TotalLevels;

    }

 

    public static  void SaveData(){

        //初始化

        if(_maxLevels ==0&&_unLockLevels==0){

            _maxLevels = 11;

            _unLockLevels =1;

        }

 

        PlayerPrefs.SetInt(“MaxLevels”,_maxLevels);

        PlayerPrefs.SetInt(“UnLockedLevels”,_unLockLevels);

    }

}


###LevelSelected.cs

D:\yanlz_DemoPro()-\小案例016、关卡系统LevelSystem\Assets\Script\LevelSelected.cs

using UnityEngine;

using System.Collections;

 

public  class  LevelSelected:MonoBehaviour{

    public GUIStyle  fontStyle;

 

    void  OnGUI(){

        if(GUI.Button(new Rect(10,10,100,100),PlayerPrefs.GetInt(“LevelId”).ToString(),fontStyle)){

            if(PlayerPrefs.GetInt(“levelId”) == LevelData._unLockLevels){

               LevelData._unLockLevels++;

            }

 

            LevelData.SaveData();

            Application.LoadLevel(0);

        }

    }

}


###MainGUI.cs

D:\yanlz_DemoPro()-\小案例016、关卡系统LevelSystem\Assets\Script\MainGUI.cs

using UnityEngine;

using System.Collecitons;

using System.Collecitons.Generic;

 

public class  MainGUI:MonoBehaviour{

    int  MaxLevel;

    LevelData  ld;

 

    void  Start(){

        LevelData.SaveData();

        MaxLevel = PlayerPrefs.GetInt(“MaxLevels”);

    }

 

    void  OnGUI(){

        for(inti=0;  i <MaxLevel;  i++){

            if(GUI.Button(new Rect(70*i,10,65,65),LevelData.addLevels()[i])){

               if(LevelData.addLevel()[i] == “unLock”){

                   PlayerPrefs.SetInt(“LevelId”,i+1);

                   Application.LoadLevel(1);

                }

            }

        }

 

        GUI.Label(new Rect(100,100,200,100),PlayerPrefs.GetInt(“MaxLevels”).ToString() + PlayerPrefs.GetInt(“UnLockedLevels”).ToString());

    }

}




#小案例017






#立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++立钻哥哥推荐的拓展学习链接(Link_Url

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++++设计模式简单整理https://blog.csdn.net/vrunsoftyanlz/article/details/79839641

++++U3D小项目参考https://blog.csdn.net/vrunsoftyanlz/article/details/80141811

++++UML类图https://blog.csdn.net/vrunsoftyanlz/article/details/80289461

++++Unity知识点0001https://blog.csdn.net/vrunsoftyanlz/article/details/80302012

++++U3D_Shader编程(第一篇:快速入门篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372071

++++U3D_Shader编程(第二篇:基础夯实篇)https://blog.csdn.net/vrunsoftyanlz/article/details/80372628

++++Unity引擎基础https://blog.csdn.net/vrunsoftyanlz/article/details/78881685

++++Unity面向组件开发https://blog.csdn.net/vrunsoftyanlz/article/details/78881752

++++Unity物理系统https://blog.csdn.net/vrunsoftyanlz/article/details/78881879

++++Unity2D平台开发https://blog.csdn.net/vrunsoftyanlz/article/details/78882034

++++UGUI基础https://blog.csdn.net/vrunsoftyanlz/article/details/78884693

++++UGUI进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78884882

++++UGUI综合https://blog.csdn.net/vrunsoftyanlz/article/details/78885013

++++Unity动画系统基础https://blog.csdn.net/vrunsoftyanlz/article/details/78886068

++++Unity动画系统进阶https://blog.csdn.net/vrunsoftyanlz/article/details/78886198

++++Navigation导航系统https://blog.csdn.net/vrunsoftyanlz/article/details/78886281

++++Unity特效渲染https://blog.csdn.net/vrunsoftyanlz/article/details/78886403

++++Unity数据存储https://blog.csdn.net/vrunsoftyanlz/article/details/79251273

++++Unity中Sqlite数据库https://blog.csdn.net/vrunsoftyanlz/article/details/79254162

++++WWW类和协程https://blog.csdn.net/vrunsoftyanlz/article/details/79254559

++++Unity网络https://blog.csdn.net/vrunsoftyanlz/article/details/79254902

++++C#事件https://blog.csdn.net/vrunsoftyanlz/article/details/78631267

++++C#委托https://blog.csdn.net/vrunsoftyanlz/article/details/78631183

++++C#集合https://blog.csdn.net/vrunsoftyanlz/article/details/78631175

++++C#泛型https://blog.csdn.net/vrunsoftyanlz/article/details/78631141

++++C#接口https://blog.csdn.net/vrunsoftyanlz/article/details/78631122

++++C#静态类https://blog.csdn.net/vrunsoftyanlz/article/details/78630979

++++C#中System.String类https://blog.csdn.net/vrunsoftyanlz/article/details/78630945

++++C#数据类型https://blog.csdn.net/vrunsoftyanlz/article/details/78630913

++++Unity3D默认的快捷键https://blog.csdn.net/vrunsoftyanlz/article/details/78630838

++++游戏相关缩写https://blog.csdn.net/vrunsoftyanlz/article/details/78630687

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/


--_--VRunSoft : lovezuanzuan--_--

参与评论 您还未登录,请先 登录 后发表或查看评论