++U3D小案例簡述
++++這裏是立鑽哥哥彙總的幾個U3D小案例,通過案例學習U3D的基本編程和技巧。
++++小案例會不斷更新補充,通過學習掌握U3D的編程和思想。
++小案例目錄:
++++小案例001、貪吃蛇Demo
++++小案例002、飛機大戰Demo
++++小案例003、MVC框架(提升等級案例)
++++小案例004、簡單揹包案例
++++小案例005、塔防Demo
++++小案例006、祕密行動Demo
++++小案例007、A_Star
++++小案例008、血條LiftBar跟隨
++++小案例009、見縫插針StickPin
++++小案例010、UnityNetDemo
++++小案例011、SocketFileRecv
++++小案例012、切水果CutFruitDemo
++++小案例013、吃雞_友軍方位UV
++++小案例014、數據庫揹包SqliteEZ_Bag
++++小案例015、Json數據存儲
++++小案例016、關卡系統LevelSystem
++++超級Demo:鬥地主
++小案例001:貪吃蛇demo
++++Cube_Snake_Body.prefab
++++Cube_Snake_Food.prefab
++++Scene02Snake.unity
++++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、耳輪跳demo
++++HudText.cs
++++BallFallScript.cs
++++CreateGap.cs
++++CreateRing.cs
++++CreateTrap.cs
++++GameMgr.cs
++++RingInfo.cs
++++RotatePillar.cs
++++SectorInfor.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;
}
}
(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;
}
}
(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);
}
}
}
}
(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);
}
}
}
(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;
}
}
}
}
}
(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();
}
}
(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.childCount; i++){
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;
}
}
}
(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);
}
}
}
(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; }
}
++小案例003、MVC框架(提升等級案例)
++++PlayerMsgController.cs
++++PlayerMsgView.cs
++++PlayerScript.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;
}
}
}
}
(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();
}
}
(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、簡單揹包案例
++++Controller/
--PlayerBagController.cs
++++Model/
--PlayerModelScript.cs
--ToolModel.cs
++++View/
--BagView.cs
--GridView.cs
--HPView.cs
--PlayerBagView.cs
--PlayerInfoView.cs
++Controller/
++++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 t1 = new ToolModel(「道具1」,ToolType.HP,2000,s1);
ToolModel t2 = new ToolModel(「道具2」,ToolType.HP,500,s2);
ToolModel t3 = new 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 obj = Instantiate<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 gv = pointerEnter.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; //在父物體的位置localPosition歸0
targetTransform = null; //清0
}
public void ClickTool(GridView grid, PointerEventData 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/
++++PlayerModelScript.cs
++++ToolModel.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]; //揹包
}
}
(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/
++++BagView.cs
++++GridView.cs
++++HPView.cs
++++PlayerBagView.cs
++++PlayerInfoView.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; //揹包界面
}
(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);
}
}
(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;
}
(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;
}
(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
++++BulletScript.cs
++++CameraMoveScript.cs
++++EndScript.cs
++++GameDataScript.cs
++++InitMonsterScript.cs
++++InitTowerScript.cs
++++MonsterScript.cs
++++TowerFireScript.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); //把子彈銷燬掉
}
}
}
(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;
}
}
(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);
}
}
}
(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.Length; i++){
//第一次循環時把默認數據賦值給第一個元素
monsterData[i].waitTime =waitTimeDefault;
monsterData[i].monsterCount = monsterCountDefault;
monsterData[i].moveSpeed =moveSpeedDefault;
//每循環一次數據增加
waitTimeDefault += 0.5f;
monsterCountDefault += 1;
moveSpeedDefault += 0.3f;
}
}
}
(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;
}
}
}
}
}
}
}
(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); //給生成的炮塔設置父物體
}
}
}
}
}
(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秒鐘後銷燬自己
}
}
}
(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、 祕密行動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、添加tag值GameController
++++3、添加英雄 char_ethan
--3.1、添加膠囊碰撞器
--3.2、添加剛體,凍結所有的旋轉以及y軸方向的位置
--3.3、添加聲音組件,聲音片段爲腳步聲
--3.4、添加動畫控制器PlayerAnimator
--3.5、添加腳本PlayerHealth,用來控制英雄的少血以及死亡
--3.6、添加腳本PlayerMove,用來控制英雄的移動
--3.7、添加tag值Player
++++4、添加平行光
--4.1、做了警報燈,顏色爲紅色,intensity=0
--4.2、添加腳本AlarmLight腳本組件,用來控制警報燈由明變暗再由暗變明
--4.3、添加tag值AlarmLight
++++5、給主攝像機添加腳本,用來控制攝像機的移動
--5.1、Editor/ProjectSetting/Physic/Hit Triggers取消勾選(否則射線會檢測觸發器,取消後只會檢測碰撞器)
--5.2、添加腳本CameraMove
++++6、在GameController上添加子物體SecondSound
--6.1、給子物體添加AudioSource組件
--6.2、添加聲音片段music_panic
--6.3、設置聲音的初始值爲0
--6.4、PlayOnAwake和Loop勾選
++++7、給警報喇叭添加標籤
--7.1、給prop_megaphon添加siren標籤
--7.2、給六個喇叭添加AudioSource組件
--7.3、添加聲音片段alarm_trigger
--7.4、設置聲音的初始值爲0
--7.5、PlayOnAwake和Loop勾選
++++8、給GameController添加腳本LastPlayerSighting
++++9、添加激光燈
--9.1、創建空物體Lasers用來管理激光門
--9.2、把fx_laserFence_lasers插到場景中並放到合適的位置(大小和旋轉)
--9.3、添加AudioSource組件,加上laser_hum聲音片段,把Loop和PlayOnAwake勾選,音量設置爲1
--9.4、添加點燈源組件,顏色爲紅色,Range=5,Intensity=1.5,Bounce=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.1、Y軸旋轉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=62,intensity=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,其餘爲0,size.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
(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;
}
}
}
}
(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.position = Vector3.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);
}
}
(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;
}
}
}
(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(); //播放聲音
}
}
}
(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; //計時器清零
}
}
}
(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;
}
}
(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);
}
}
(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 distance = Vector3.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;
}
}
(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」);
}
}
(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(pickAud, transform.position); //播放聲音
Destroy(gameObject); //銷燬自己
}
}
}
(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;
}
}
}
(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();
}
}
}
(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);
}
}
}
}
(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」);
}
}
}
}
}
(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」);
}
}
(D:\zz_DemoPro()-\小案例006、祕密行動Demo\Demo006_StealthActionDemo\Assets\Scripts\PlayerInventory.cs)
using UnityEngine;
using System.Collections;
public class PlayerInventory:MonoBehaviour{
public boolhasKey=false; //玩家是否擁有鑰匙
}
(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(); //停止播放腳步聲
}
}
}
(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);
}
}
(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」;
}
++小案例007、A_Star
++++FindPath.cs
++++GridMap.cs
++++Node.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<Node> path =new List<Node>();
Node temp = endNode;
while(temp !=startNode){
path.Add(temp);
temp = temp.parent;
}
path.Reverse();
_grid.path=path;
}
}
(D:\yanlz_DemoPro()-\小案例007、AStar\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<Node> GetNeibourhood(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;
}
}
(D:\yanlz_DemoPro()-\小案例007、AStar\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跟隨
++++FaceToCamera.cs
++++HeadHP.cs
++++HPTest.cs
++++PlayerMove.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);
}
}
(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;
}
}
}
(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;
}
}
(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
++++GameManager.cs
++++Pin.cs
++++PinHead.cs
++++RotateSelf.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);
}
}
(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.position = targetCirclePos;
transform.parent =circle;
isFly =false;
}
}
}
}
public void StartFly(){
isFly = true;
isReach = true;
}
}
(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();
}
}
}
(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));
}
}
#小案例010、UnityNetDemo
++++Player.cs
(D:\yanlz_DemoPro()-\小案例010、UnityNetDemo\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;
}
}
#小案例011、SocketFileRecv
++++Server\Program.cs
++++Client\Program.cs
(D:\yanlz_DemoPro()-\小案例011、socketFileRecv\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);
}
}
}
(D:\yanlz_DemoPro()-\小案例011、socketFileRecv\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
++++MouseControl.cs
++++DestroyOnTime.cs
++++ObjectControl.cs
++++Spawner.cs
++++UIOver.cs
++++UIScore.cs
++++UIStart.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);
}
}
}
(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);
}
}
(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;
}
}
(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);
}
}
(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);
}
}
(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.text = this.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();
}
}
(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
++++CoordScript.cs
++++FriendMoveScript.cs
++++CameraScript.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;
}
}
(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);
}
}
(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
++++DataBaseController.cs
++++HeroMessage.cs
++++SqliteDataScripts.cs
++++StoreWeapon.cs
++++WeaponBox.cs
(D:\yanlz_DemoPro()-\小案例014、SqliteEZ_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 query:SQL語句
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;
}
}
}
(D:\yanlz_DemoPro()-\小案例014、SqliteEZ_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(); //關閉數據庫
}
}
(D:\yanlz_DemoPro()-\小案例014、SqliteEZ_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();
//查詢方法1:ExecuteScalar
//command.ExecuteScalar(); //返回所有結果中的第一個查詢到的值
//查詢方法2:ExecuteReader
//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、關閉數據庫
}
}
(D:\yanlz_DemoPro()-\小案例014、SqliteEZ_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);
}
}
}
(D:\yanlz_DemoPro()-\小案例014、SqliteEZ_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」);
}
}
}
#小案例015、Json數據存儲
++++CubeItem.cs
++++CubeManager.cs
++++CubeTest.cs
++++JsonDemo.cs
++++Person.cs
(D:\yanlz_DemoPro()-\小案例015、Json數據存儲\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);
}
}
(D:\yanlz_DemoPro()-\小案例015、Json數據存儲\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<CubeItem> cubeList; //Cube對象
private List<CubeItem> posList; //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);
}
}
}
(D:\yanlz_DemoPro()-\小案例015、Json數據存儲\Assets\Scripts\CubeTest.cs)
using UnityEngine;
using System.Collections;
using LitJson;
public class CubeTest:MonoBehaviour{
private Transform m_Transform;