做了許多的AR互動遊戲總結了一下期間的所需,根據其需求以及網上的資料查詢整合了一些常用的屬性編寫了一套比較適合自己的小型框架。
首先我們知道AR所需要的功能
1.邏輯功能,大部分是一個一個的小型關卡和邏輯組成,所以這裏我選擇了有限狀態機來實現一個關卡和一個關卡之間的邏輯。
2.其次是部分功能,大部分遊戲由一個GameManger管理類,所以我們需要一個單例模板。
3.很多關卡是由時間控制,時間是由圖片的切換來完成所以我們需要一個時間類,來時常調用。
4.無論砸球和體感都需要一個分數來實現,所以也需要一個分數類。
5.大部分物體,例如特效反覆的實例化刪除很耗性能一個不小心容易導致內存泄露所以使用一個內存池可以很好的控制這個發生的機率
6.數據載入,做一個沙池遊戲中,一些教育類遊戲會需要大量的文字顯示,這樣的話使用Xml會很方便,當然數據的載入也能使用,有時候也會用到txt載入看自己選擇了。
7.音效管理類,之前都是哪裏有音效直接掛哪裏然後代碼播放停止,現在學習之後用了一個類,使代碼更加的簡潔。
8.常用的一些方法,例如協程,和每隔一段時間需要重複一個邏輯。
下面就讓我一個一個來實現
1。首先先實現有限狀態機的框架這個之前也有分享過直接上代碼
1.1狀態機類
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
/// <summary>
/// 狀態接口
/// </summary>
public interface Istate
{
/// <summary>
/// 狀態名
/// </summary>
string Name { get; }
/// <summary>
/// 狀態標籤
/// </summary>
string Tag { set; get; }
/// <summary>
/// 當前狀態的狀態機
/// </summary>
IstateMachine Parent { get; set; }
/// <summary>
/// 從進入狀態開始計算的時長
/// </summary>
float Timer { get; }
/// <summary>
/// 狀態過度當前狀態的所有過度
/// </summary>
List<ITransition> Transition { get; }
/// <summary>
/// 進入狀態時的回調
/// </summary>
/// <param name="prev">上一個狀態</param>
void EnterCallback(Istate prev);
/// <summary>
/// 退出狀態時的回調
/// </summary>
/// <param name="next">下一個狀態</param>
void ExitCallback(Istate next);
/// <summary>
/// Update的回調
/// </summary>
/// <param name="deltaTime">Time.deltaTime</param>
void UpdateCallback(float deltaTime);
/// <summary>
/// LateUpdate的回調
/// </summary>
/// <param name="deltaTime">Time.deltaTime</param>
void LateUpdateCallback(float deltaTime);
/// <summary>
/// FixUppdate的回調
/// </summary>
void FixUppdateCallback();
/// <summary>
/// 添加過度
/// </summary>
/// <param name="t">狀態過度</param>
void AddTransition(ITransition t);
}
}
1.2.狀態機工廠
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
/// <summary>
/// 狀態機接口
/// </summary>
public interface IstateMachine
{
/// <summary>
/// 當前狀態
/// </summary>
Istate CurrentState { get; }
/// <summary>
/// 默認狀態
/// </summary>
Istate DefaultState { set; get; }
/// <summary>
/// 添加狀態
/// </summary>
/// <param name="state">要添加的狀態</param>
void AddState(Istate state);
/// <summary>
/// 刪除狀態
/// </summary>
/// <param name="state">要刪除的狀態</param>
void RemoveState(Istate state);
/// <summary>
/// 通過指定的tag值查找狀態
/// </summary>
/// <param name="tag">狀態 Tag值</param>
/// <returns>查找到的狀態</returns>
Istate GetStateWithTage(string tag);
}
}
1.3狀態機回掉
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
public delegate void LexDelegate();
public delegate void LexDelegateState(Istate State);
public delegate void LexDelegateFloat(float f);
public class LexState : Istate
{
/// <summary>
/// 當進入狀態時調用的事件
/// </summary>
public event LexDelegateState OnEnter;
/// <summary>
/// 當離開狀態時調用的事件
/// </summary>
public event LexDelegateState OnExit;
/// <summary>
/// 當Update時調用的事件
/// </summary>
public event LexDelegateFloat OnUpdate;
/// <summary>
/// 當LateUpdate時調用的事件
/// </summary>
public event LexDelegateFloat OnLateUpdate;
/// <summary>
/// 當FixUpdate時調用的事件
/// </summary>
public event LexDelegate OnFixUpdate;
private string _name;//狀態名
private string _tag;//狀態標籤
private IstateMachine _parent;//當前狀態的狀態機
private float _Timer;//計時器
private List<ITransition> _transition;//狀態過度
/// <summary>
/// 構造方法
/// </summary>
/// <param name="name">狀態名</param>
public LexState(string name)
{
_name = name;
_transition = new List<ITransition>();
}
/// <summary>
/// 狀態名
/// </summary>
public string Name
{
get
{
return _name;
}
}
/// <summary>
/// 狀態標籤
/// </summary>
public string Tag
{
get
{
return _tag;
}
set
{
_tag = value;
}
}
/// <summary>
/// 當前狀態的狀態機
/// </summary>
public IstateMachine Parent
{
get
{
return _parent;
}
set
{
_parent = value;
}
}
/// <summary>
/// 從進入狀態開始計算的時長
/// </summary>
public float Timer
{
get
{
return _Timer;
}
}
/// <summary>
/// 狀態過度當前狀態的所有過度
/// </summary>
public List<ITransition> Transition
{
get
{
return _transition;
}
}
/// <summary>
/// 添加過度
/// </summary>
/// <param name="t">狀態過度</param>
public void AddTransition(ITransition t)
{
if(t!=null&&!_transition.Contains(t))
{
_transition.Add(t);
}
}
/// <summary>
/// 進入狀態時的回調
/// </summary>
/// <param name="prev">上一個狀態</param>
public virtual void EnterCallback(Istate prev)
{
//重置計時器
_Timer = 0;
//進入狀態時系統調用OnEnter事件
if (OnEnter != null)
{
OnEnter(prev);
}
}
/// <summary>
/// 退出狀態時的回調
/// </summary>
/// <param name="next">下一個狀態</param>
public virtual void ExitCallback(Istate next)
{
//離開狀態時系統調用OnEnter事件
if (OnExit != null)
{
OnExit(next);
}
//重置計時器
_Timer = 0;
}
/// <summary>
/// Update的回調
/// </summary>
/// <param name="deltaTime">Time.deltaTime</param>
public virtual void UpdateCallback(float deltaTime)
{
//累加計時器
_Timer += deltaTime;
//Update時系統會調用OnUpdate事件
if (OnUpdate!=null)
{
OnUpdate(deltaTime);
}
}
/// <summary>
/// LateUpdate的回調
/// </summary>
/// <param name="deltaTime">Time.deltaTime</param>
public virtual void LateUpdateCallback(float deltaTime)
{
//LateUpdate時系統會調用OnLateUpdate事件
if (OnLateUpdate!=null)
{
OnLateUpdate(deltaTime);
}
}
/// <summary>
/// FixUppdate的回調
/// </summary>
public virtual void FixUppdateCallback()
{
//FixUpdate時系統會調用OnFixUpdate事件
if (OnFixUpdate!=null)
{
OnFixUpdate();
}
}
}
}
1.4狀態機回調工廠
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
/// <summary>
/// 狀態機類需要繼承與狀態類並實現狀態機接口
/// </summary>
public class LexStateMachine : LexState, IstateMachine
{
private Istate _CurrentState;//當前狀態
private Istate _DefaultState;//默認狀態
private List<Istate> _States;//所有狀態
private bool _isTransition = false;//是否正在過度
private ITransition _t;//當前正在執行的過度
/// <summary>
/// 構造方法
/// </summary>
/// <param name="name"></param>
public LexStateMachine(string name,Istate defaultState):base(name)
{
_States = new List<Istate>();
_DefaultState = defaultState;
_DefaultState.EnterCallback(defaultState);
}
/// <summary>
/// 當前狀態
/// </summary>
public Istate CurrentState
{
get
{
return _CurrentState;
}
}
/// <summary>
/// 默認狀態
/// </summary>
public Istate DefaultState
{
get
{
return _DefaultState;
}
set
{
AddState(value);
_DefaultState = value;
}
}
/// <summary>
/// 添加狀態
/// </summary>
/// <param name="state">要添加的狀態</param>
public void AddState(Istate state)
{
if(state!=null &&!_States.Contains(state))
{
_States.Add(state);
//將加入的新狀態的的Parent設置爲當前狀態機
state.Parent = this;
if(_DefaultState==null)
{
_DefaultState = state;
}
}
}
/// <summary>
/// 刪除狀態
/// </summary>
/// <param name="state">要刪除的狀態</param>
public void RemoveState(Istate state)
{
//再狀態機運行過程中不能夠刪除當前狀態
if (_CurrentState == state)
{
return;
}
if (state != null && _States.Contains(state))
{
_States.Remove(state);
//將已經移除的Parent設置爲空
state.Parent = null;
if (_DefaultState == state)
{
_DefaultState = (_States.Count >= 1) ? _States[0] : null;
}
}
}
/// <summary>
/// 通過指定的tag值查找狀態
/// </summary>
/// <param name="tag">狀態 Tag值</param>
/// <returns>查找到的狀態</returns>
public Istate GetStateWithTage(string tag)
{
return null;
}
public override void UpdateCallback(float deltaTime)
{
//檢測當前是否再過度狀態
if(_isTransition)
{
//檢測當前執行的過度是否完成
if(_t.TransitionCallback())
{
DoTransition(_t);
_isTransition = false;
}
return;
}
base.UpdateCallback(deltaTime);
if(_CurrentState==null)
{
_CurrentState = _DefaultState;
}
List<ITransition> ts = _CurrentState.Transition;
int Count = _CurrentState.Transition.Count;
for (int i = 0; i < Count; i++)
{
ITransition t = ts[i];
if(t.ShouldBengin())
{
_isTransition = true;
_t = t;
return;
}
}
_CurrentState.UpdateCallback(deltaTime);
}
public override void LateUpdateCallback(float deltaTime)
{
base.LateUpdateCallback(deltaTime);
_CurrentState.LateUpdateCallback(deltaTime);
}
public override void FixUppdateCallback()
{
base.FixUppdateCallback();
_CurrentState.FixUppdateCallback();
}
//開始執行過度
private void DoTransition(ITransition t)
{
_CurrentState.ExitCallback(t.To);
_CurrentState = t.To;
_CurrentState.EnterCallback(t.From);
}
}
}
1.5狀態機過度類
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
/// <summary>
/// 狀態過度的接口
/// </summary>
public interface ITransition
{
/// <summary>
/// 過度名
/// </summary>
string name { get; }
/// <summary>
/// 從哪個狀態開始過度
/// </summary>
Istate From { get; set; }
/// <summary>
/// 要過度到哪個狀態去
/// </summary>
Istate To { get; set; }
/// <summary>
/// 過度時的回調
/// </summary>
/// <returns>返回true過度結束返回false繼續進行過度</returns>
bool TransitionCallback();
/// <summary>
/// 能否開始過度
/// </summary>
/// <returns>如果是True就開始進行過度如果是False就不進行過度</returns>
bool ShouldBengin();
}
}
1.6過渡實現
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace FSM
{
public delegate bool LexTransitionDelegate();
public class LexTransition : ITransition
{
private Istate _From;//原狀態
private Istate _To;//目標狀態
private string _name;//過度名
public event LexTransitionDelegate OnTransition;
public event LexTransitionDelegate OnCheck;//檢測條件是否滿足
/// <summary>
/// 構造方法
/// </summary>
/// <param name="Name"></param>
/// <param name="fromstate"></param>
/// <param name="tostate"></param>
public LexTransition(string Name, Istate fromstate, Istate tostate)
{
_name = Name;
_From = fromstate;
_To = tostate;
}
/// <summary>
/// 過度名
/// </summary>
public string name
{
get
{
return _name;
}
}
/// <summary>
/// 從哪個狀態開始過度
/// </summary>
public Istate From
{
get
{
return _From;
}
set
{
_From = value;
}
}
/// <summary>
/// 要過度到哪個狀態去
/// </summary>
public Istate To
{
get
{
return _To;
}
set
{
_To = value;
}
}
/// <summary>
/// 過度時的回調
/// </summary>
/// <returns>返回true過度結束返回false繼續進行過度</returns>
public bool TransitionCallback()
{
if (OnTransition != null)
{
return OnTransition();
}
return true;
}
/// <summary>
/// 能否開始過度
/// </summary>
/// <returns>如果是True就開始進行過度如果是False就不進行過度</returns>
public bool ShouldBengin()
{
if (OnCheck != null)
{
return OnCheck();
}
return false;
}
}
}
1.7 狀態機框架調用
1.7.1一個狀態機一個類來實現
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FSM;
public class lightText : MonoBehaviour {
private LexState OpenState;//燈光的打開狀態
private LexState CloseState;//燈光的關閉狀態
private Light _light;
// Use this for initialization
void Awake ()
{
_light = GetComponent<Light>();
OpenState = new LexState("_OpenState");
//燈光再打開狀態的時候實時打印
OpenState.OnUpdate += (float f) =>
{
Debug.Log("Hello, World");
};
OpenState.OnEnter += new LexDelegateState(WillEnterState);
CloseState = new LexState("CloseState");
CloseState.OnExit += (Istate State) =>
{
Debug.Log("即將離開關閉狀態");
};
}
//即將進入打開狀態時調用
private void WillEnterState(Istate prev)
{
Debug.Log("即將進入打開狀態");
_light.color = Color.blue;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FSM;
public class Test : MonoBehaviour {
public float speed; //Cube每秒鐘移動的距離
private LexStateMachine _fsm;//狀態機
private LexState Idle;//閒置狀態
private LexState move;//移動狀態
private LexTransition _IdleToMove;//Idle到Move的狀態過度
private LexTransition _MoveToIdle;//Move到Idle的狀態過度
private bool IsMove=false;//能否開始移動
// Use this for initialization
void Start () {
//初始化狀態
Idle = new LexState("Idle");//創建狀態
//Idle.EnterCallback(_fsm.CurrentState);
Idle.OnEnter += (Istate state) =>
{
Debug.Log("進入Idle狀態");
};
move = new LexState("Move");
//移動狀態的時候的邏輯
move.OnUpdate += (float f) =>
{
transform.position += transform.forward * f * speed;
};
_IdleToMove = new LexTransition("idlemove", Idle, move);//創建過渡狀態
_IdleToMove.OnCheck += () =>
{
return IsMove;
};
Idle.AddTransition(_IdleToMove);//加入過渡狀態鏈表
//_IdleToMove.OnTransition += () =>
// {
// };
_MoveToIdle = new LexTransition("moveIdle", move, Idle);
_MoveToIdle.OnCheck += () =>
{
return !IsMove;
};
move.AddTransition(_MoveToIdle);
_fsm = new LexStateMachine("Root", Idle);//創建狀態機並加入狀態
_fsm.AddState(move);
}
// Update is called once per frame
void Update () {
_fsm.UpdateCallback(Time.deltaTime);
}
void OnGUI()
{
if(GUILayout.Button("move"))
{
IsMove = true;
}
if(GUILayout.Button("Stop"))
{
IsMove = false;
}
}
}
1.7.2狀態機整體調用並且可以實現層級狀態機
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FSM;
public class LightControl : MonoBehaviour {
public float maxIntensity;
public float FadeSpeed;
private LexStateMachine _fsm;
private LexStateMachine _open;//open狀態下的子狀態聲明
private LexState _close;
private LexTransition opentoclose;
private LexTransition closetoopen;
private LexState _changeIntensity;
private LexState _changeColor;
private LexTransition colortointensity;
private LexTransition intensitytocolor;
private bool isOpen=true;
private bool isAnimation;
private bool isResst;
private float target;
private Color targetColor;
private Color StartColor;
private float ColorTimer;
public bool ischangecolor;
private Light _light;
// Use this for initialization
void Start () {
InitFSM();
_light = GetComponent<Light>();
}
// Update is called once per frame
void Update () {
_fsm.UpdateCallback(Time.deltaTime);
}
//初始化狀態機
private void InitFSM()
{
_changeIntensity = new LexState("changeIntensity");
_changeIntensity.OnEnter += (Istate State) =>
{
isAnimation = true;
isResst = true;
};
_changeIntensity.OnUpdate += (float f) =>
{
if (isAnimation)
{
if (isResst)
{
if (Fadeto(maxIntensity))
{
isResst = false;
isAnimation = false;
}
}
else
{
if (Fadeto(target))
{
isResst = true;
}
}
}
else
{
target = Random.Range(0.3f, 0.7f);
isAnimation = true;
}
};
_changeColor = new LexState("changeColor");
_changeColor.OnEnter += (Istate State) =>
{
isAnimation = false;
};
_changeColor.OnUpdate += (float f) =>
{
if(isAnimation)
{
if(ColorTimer>=1f)
{
isAnimation = false;
}
else
{
ColorTimer += Time.deltaTime ;
_light.color = Color.Lerp(StartColor, targetColor, ColorTimer);
}
}
else
{
float r = Random.Range(0,0.5f);
float g = Random.Range(0, 0.5f);
float b = Random.Range(0, 0.5f);
targetColor = new Color(r, g, b);
StartColor = _light.color;
ColorTimer = 0f;
isAnimation = true;
}
};
colortointensity = new LexTransition("colortointensity",_changeColor,_changeIntensity);
colortointensity.OnCheck += () =>
{
return !ischangecolor;
};
_changeColor.AddTransition(colortointensity);
intensitytocolor = new LexTransition("intensitytocolor", _changeIntensity, _changeColor);
intensitytocolor.OnCheck += () =>
{
return ischangecolor;
};
_changeIntensity.AddTransition(intensitytocolor);
_open = new LexStateMachine("open", _changeIntensity);//子狀態的加入
_open.AddState(_changeColor);
_close = new LexState("close");
_close.OnEnter += (Istate State) =>
{
_light.intensity = 0;
};
opentoclose = new LexTransition("OpenClose", _open, _close);
opentoclose.OnCheck += () =>
{
return !isOpen;
};
//opentoclose.OnTransition += () =>
//{
// return Fadeto(0);
//};
_open.AddTransition(opentoclose);
closetoopen = new LexTransition("CloseOpen", _close, _open);
closetoopen.OnCheck += () =>
{
return isOpen;
};
closetoopen.OnTransition += () =>
{
return Fadeto(maxIntensity);
};
_close.AddTransition(closetoopen);
_fsm = new LexStateMachine("Cube", _open);
_fsm.AddState(_close);
}
void OnGUI()
{
if (GUI.Button(new Rect(150f,30f,55f,28f),"open"))
{
isOpen = true;
}
if (GUI.Button(new Rect(150f, 65f, 55f, 28f), "Close"))
{
isOpen = false;
}
}
//將燈光光強漸變到指定的值
private bool Fadeto(float f)
{
if(Mathf.Abs(_light.intensity-f)<=0.05f)
{
_light.intensity = f;
return true;
}
else
{
int flag = _light.intensity > f ? -1 : 1;
_light.intensity += Time.deltaTime * FadeSpeed*flag;
return false;
}
}
}
2 單例模板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FSM;
public class Test : MonoBehaviour {
public float speed; //Cube每秒鐘移動的距離
private LexStateMachine _fsm;//狀態機
private LexState Idle;//閒置狀態
private LexState move;//移動狀態
private LexTransition _IdleToMove;//Idle到Move的狀態過度
private LexTransition _MoveToIdle;//Move到Idle的狀態過度
private bool IsMove=false;//能否開始移動
// Use this for initialization
void Start () {
//初始化狀態
Idle = new LexState("Idle");//創建狀態
//Idle.EnterCallback(_fsm.CurrentState);
Idle.OnEnter += (Istate state) =>
{
Debug.Log("進入Idle狀態");
};
move = new LexState("Move");
//移動狀態的時候的邏輯
move.OnUpdate += (float f) =>
{
transform.position += transform.forward * f * speed;
};
_IdleToMove = new LexTransition("idlemove", Idle, move);//創建過渡狀態
_IdleToMove.OnCheck += () =>
{
return IsMove;
};
Idle.AddTransition(_IdleToMove);//加入過渡狀態鏈表
//_IdleToMove.OnTransition += () =>
// {
// };
_MoveToIdle = new LexTransition("moveIdle", move, Idle);
_MoveToIdle.OnCheck += () =>
{
return !IsMove;
};
move.AddTransition(_MoveToIdle);
_fsm = new LexStateMachine("Root", Idle);//創建狀態機並加入狀態
_fsm.AddState(move);
}
// Update is called once per frame
void Update () {
_fsm.UpdateCallback(Time.deltaTime);
}
void OnGUI()
{
if(GUILayout.Button("move"))
{
IsMove = true;
}
if(GUILayout.Button("Stop"))
{
IsMove = false;
}
}
}
2.1單例模板使用,很簡單直接在所需單例類的後面繼承,並在<>寫上這個類調用單例類方法,類名.Instance.方法名。
3.時間管理類,這個是按分秒顯示的如果只想用秒可以稍作改進
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class TimeManager : UnitySingleton<TimeManager>
{
public int minite;//分
public int second;//秒
public float Timer;//時間
public Sprite[] NumberSprite;//存放數字圖片
public GameObject[] TimeDisplay;//存放UIGameObject
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
Timer -= Time.deltaTime;
minite = (int)Timer / 60;
second = (int)Timer % 60;
//秒第個位
if(second>=0&&second<60)
{
TimeDisplay[0].GetComponent<Image>().sprite = NumberSprite[FindNum(second, 1)];
}
//秒十位
if (second >= 0 && second < 60)
{
TimeDisplay[1].GetComponent<Image>().sprite = NumberSprite[FindNum(second, 2)];
}
//分個位
if(minite>=0&& minite < 10)
{
TimeDisplay[2].GetComponent<Image>().sprite = NumberSprite[FindNum(minite, 1)];
}
//分十位
if (minite >= 10 && minite < 60)
{
TimeDisplay[3].GetComponent<Image>().sprite = NumberSprite[FindNum(minite, 2)];
}
}
/// <summary>
/// 分數顯示
/// </summary>
/// <param name="num">數字</param>
/// <param name="n">位數</param>
/// <returns></returns>
public int FindNum(int num, int n)
{
int power = (int)Math.Pow(10, n);
return (num - num / power * power) * 10 / power;
}
}
4.分數類,實現一個簡單的分數滾動機制
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class Score : MonoBehaviour
{
public Sprite[] ScoreSprite;//數字貼圖
static public int CurrentScore;//當前分數
static public int OriginalScore;//原始的分數
public GameObject[] ScoreDisplay;//分數顯示
float timeKeep = 0.1f;//多久滾動時間
private float ChangeTime;//時間變量
// Use this for initialization
void Start()
{
CurrentScore = 0;
OriginalScore = 0;
ChangeTime = 0;
}
// Update is called once per frame
void Update()
{
if (CurrentScore < 0)
{
CurrentScore = 0;
}
if (OriginalScore != CurrentScore)
{
ChangeTime += Time.deltaTime;
if (ChangeTime > timeKeep)
{
if (OriginalScore < CurrentScore)
{
OriginalScore++;
}
if (OriginalScore > CurrentScore)
{
OriginalScore--;
}
ChangeScore(OriginalScore);
ChangeTime = 0;
int dis = Math.Abs(OriginalScore - CurrentScore);
timeKeep = 0.01f / (float)(dis % 10 + 1);
}
}
}
/// <summary>
/// 改變分數
/// </summary>
/// <param name="Number">分數</param>
public void ChangeScore(int Number)
{
char[] chars = Number.ToString().ToCharArray();
for (int i = 0; i < chars.Length; i++)
{
int index = int.Parse(chars[chars.Length - i - 1].ToString());
ScoreDisplay[i].GetComponent<Image>().sprite = ScoreSprite[index];
}
for (int i = 0; i < ScoreDisplay.Length- chars.Length; i++)
{
ScoreDisplay[ScoreDisplay.Length-1-i].GetComponent<Image>().sprite = ScoreSprite[0];
}
}
}
5內存池,大部分重複使用的物體可以存放在裏面,例如特效
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class Pool : UnitySingleton<Pool>
{
//將要製作成對象池的Prefab拖到此數組中
public GameObject[] prefabArray;
Dictionary<string, SubPool> m_pools = new Dictionary<string, SubPool>();
void Start()
{
DontDestroyOnLoad(this.gameObject);
}
void OnEnable()
{
}
/// <summary>
/// 物體被銷燬時 OnDisable將被調用,並且可用於任意清理代碼。腳本被卸載時,OnDisable將被調用,OnEnable在腳本被載入後調用
/// </summary>
void OnDisable()
{
foreach (var pool in m_pools)
{
pool.Value.m_objects.Clear();
}
m_pools.Clear();
}
public GameObject Spwan(GameObject obj)
{
if (!m_pools.ContainsKey(obj.name))
CreatNewSubPool(obj);
SubPool pool = m_pools[obj.name];
return pool.Spawn();
}
public void UnSpwan(GameObject go)
{
SubPool pool = null;
foreach (SubPool p in m_pools.Values)
{
if (p.Contains(go))
{
pool = p;
break;
}
}
pool.Unspawn(go);
}
public void UnspawnAll()
{
foreach (SubPool p in m_pools.Values)
p.UnspawnAll();
}
public void CreatNewSubPool(GameObject obj)
{
string name = obj.name;
if (!m_pools.ContainsKey(name))
{
SubPool pool = new SubPool(transform,obj);
m_pools.Add(name, pool);
}
}
}
public class SubPool
{
GameObject m_prefab;
Transform m_parent;
public List<GameObject> m_objects = new List<GameObject>();
public SubPool(Transform parent, GameObject obj)
{
this.m_parent = parent;
this.m_prefab = obj;
}
public GameObject Spawn()
{
GameObject go = null;
foreach (GameObject obj in m_objects)
{
if (!obj.activeSelf)
{
go = obj;
break;
}
}
if (go == null)
{
go = GameObject.Instantiate<GameObject>(m_prefab);
go.transform.parent = m_parent;
m_objects.Add(go);
}
go.SetActive(true);
return go;
}
//回收對象
public void Unspawn(GameObject go)
{
if (Contains(go))
{
go.SetActive(false);
}
}
//回收該池子的所有對象
public void UnspawnAll()
{
foreach (GameObject item in m_objects)
{
if (item.activeSelf)
{
Unspawn(item);
}
}
}
//是否包含對象
public bool Contains(GameObject go)
{
return m_objects.Contains(go);
}
}
6.數據載入Xml
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml;
using System.IO;
public class XmlLoad : UnitySingleton<XmlLoad>
{
#region Public Variables
public string LocalUrl = Application.streamingAssetsPath + "/Text.xml"; //Xml路徑
public List<string> AllTitleName = new List<string>(); //所有標題名字
public List<string> Content = new List<string>();//所有內容
#endregion
#region Methods
public XmlDocument ReadAndLoadXml()
{
XmlDocument doc = new XmlDocument();
doc.Load(LocalUrl);
return doc;
}
/// <summary>
/// 讀取xml信息
/// </summary>
/// <param name="id">等級ID</param>
/// <param name="attributeName">屬性名稱</param>
/// <returns></returns>
public string ParseXml(int id)
{
string result = null;
XmlReaderSettings set = new XmlReaderSettings();
set.IgnoreComments = true;//這個設置是忽略xml註釋文檔的影響。有時候註釋會影響到xml的讀取
//得到Levels節點下的所有子節點
XmlNodeList xmlNodeList = ReadAndLoadXml().SelectSingleNode("Levels").ChildNodes;
foreach (XmlElement item in xmlNodeList)
{
if (item.GetAttribute("ID") == id.ToString())
{
AllTitleName = new List<string>();
Content = new List<string>();
foreach (XmlElement item1 in item.ChildNodes)
{
//遍歷id下的子節點加入鏈表
AllTitleName.Add(item1.GetAttribute("Title"));
Content.Add(item1.GetAttribute("Content"));
}
}
}
return result;
}
/// <summary>
/// 修改Xml
/// </summary>
/// <param name="OriginalId"></param>
/// <param name="NewId"></param>
public void updateXML(int OriginalId,int NewId)
{
if (File.Exists(LocalUrl))
{
XmlDocument xml = new XmlDocument();
//得到Levels節點下的所有子節點
XmlNodeList xmlNodeList = ReadAndLoadXml().SelectSingleNode("Levels").ChildNodes;
foreach (XmlElement item in xmlNodeList)
{
if (item.GetAttribute("ID") == OriginalId.ToString())
{
//改變messages裏id
item.SetAttribute("ID", NewId.ToString());
}
if (item.GetAttribute("ID") == OriginalId.ToString())
{
foreach (XmlElement item1 in item.ChildNodes)
{
//改變子節點
}
}
}
xml.Save(LocalUrl);
}
}
/// <summary>
/// 創建Xml
/// </summary>
public void CreateXML()
{
//string path = Application.dataPath + "/data2.xml";
if (!File.Exists(LocalUrl))
{
//創建最上一層的節點。
XmlDocument xml = new XmlDocument();
//創建最上一層的節點。
XmlElement root = xml.CreateElement("objects");
//創建子節點
XmlElement element = xml.CreateElement("messages");
//設置節點的屬性
element.SetAttribute("id", "1");
XmlElement elementChild1 = xml.CreateElement("contents");
elementChild1.SetAttribute("name", "a");
//設置節點內面的內容
elementChild1.InnerText = "這就是你,你就是天狼";
XmlElement elementChild2 = xml.CreateElement("mission");
elementChild2.SetAttribute("map", "abc");
elementChild2.InnerText = "去吧,少年,去實現你的夢想";
//把節點一層一層的添加至xml中,注意他們之間的先後順序,這是生成XML文件的順序
element.AppendChild(elementChild1);
element.AppendChild(elementChild2);
root.AppendChild(element);
xml.AppendChild(root);
//最後保存文件
xml.Save(LocalUrl);
}
}
/// <summary>
/// 添加Xml
/// </summary>
public void addXMLData()
{
///string path = Application.dataPath + "/data2.xml";
if (File.Exists(LocalUrl))
{
XmlDocument xml = new XmlDocument();
xml.Load(LocalUrl);
XmlNode root = ReadAndLoadXml().SelectSingleNode("Levels");
//下面的東西就跟上面創建xml元素是一樣的。我們把他複製過來就行了
XmlElement element = xml.CreateElement("messages");
//設置節點的屬性
element.SetAttribute("id", "2");
XmlElement elementChild1 = xml.CreateElement("contents");
elementChild1.SetAttribute("name", "b");
//設置節點內面的內容
elementChild1.InnerText = "天狼,你的夢想就是。。。。。";
XmlElement elementChild2 = xml.CreateElement("mission");
elementChild2.SetAttribute("map", "def");
elementChild2.InnerText = "我要妹子。。。。。。。。。。";
//把節點一層一層的添加至xml中,注意他們之間的先後順序,這是生成XML文件的順序
element.AppendChild(elementChild1);
element.AppendChild(elementChild2);
root.AppendChild(element);
xml.AppendChild(root);
//最後保存文件
xml.Save(LocalUrl);
}
}
#endregion
#region Main
#endregion
}
6.1Xml文檔
<?xml version="1.0" encoding="UTF-8"?>
-<Levels>
-<Level ID="1">
<contents Content="helloWord!" Title="helloWord!"/>
<contents Content="helloWord!" Title="helloWord!/>
<contents Content="翼龍又名翼手龍,是一種已經滅絕的爬行類,儘管與恐龍生存的時代相同,但翼龍並不是恐龍。希臘文意思爲“有翼蜥蜴”,是飛行爬行動物演化支。 生存於晚三疊紀到白堊紀末,約2億1000萬年前到6500萬年前。翼龍類是第一種飛行的脊椎動物,翼龍的翼是從位於身體側面到四節翼指骨之間的皮膚膜衍生出來的。較早的物種有長而佈滿牙齒的顎部,以及長尾巴;較晚的物種有大幅縮短的尾巴,而且缺乏牙齒。翼龍類的體型有非常大的差距,從小如鳥類的森林翼龍,到地球上曾出現的最大型飛行生物。" Title="翼龍"/>
</Level>
-<Level ID="2">
<contents Content="" Title=""/>
<contents Content="" Title=""/>
<contents Content="" Title=""/>
</Level>
-<Level ID="3">
<contents Content="" Title=""/>
<contents Content="" Title=""/>
<contents Content="" Title=""/>
</Level>
</Levels>
6.2txt讀取
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System;
public class LoadTxt : MonoBehaviour
{
string _url;
public string[] LineStrings;
void Start()
{
LoadTxtOnDatePath("my");
}
void Update()
{
}
public void LoadTxtOnDatePath(string txtName)
{
string _datePath = Application.dataPath;
int _num = _datePath.LastIndexOf("/");
_datePath = _datePath.Substring(0, _num);
_url = _datePath + "/" + txtName + ".txt";
try
{
string[] strs = File.ReadAllLines(_url);
if (LineStrings != null)
{
for (int i = 0; i < LineStrings.Length; i++)
{
LineStrings[i] = ReadFile(strs, i);
}
}
}
catch (Exception e)
{
Debug.Log(e);
}
}
string ReadFile(string[] strs, int lineNum)
{
if (lineNum == 0)
{
return "";
}
else
{
if (lineNum < strs.Length + 1)
{
return strs[lineNum - 1];
}
else
{
return "";
}
}
}
}
7音效管理類,調用就可以直接用方法來調用Resources下Audio中的名字。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AudioSourceControl : UnitySingleton<AudioSourceControl>
{
/// <summary>
/// *音樂管理器
/// </summary>
///
private Dictionary<string, int> AudioDictionary = new Dictionary<string, int>();
private const int MaxAudioCount = 10;
private const string ResourcePath = "Audio/";
private const string StreamingAssetsPath = "";
private AudioSource BGMAudioSource;
private AudioSource LastAudioSource;
#region Mono Function
#endregion
/// <summary>
/// 播放
/// </summary>
/// <param name="audioname"></param>
public void SoundPlay(string audioname, float volume = 1)
{
if (AudioDictionary.ContainsKey(audioname))
{
if (AudioDictionary[audioname] <= MaxAudioCount)
{
AudioClip sound = this.GetAudioClip(audioname);
if (sound != null)
{
StartCoroutine(this.PlayClipEnd(sound, audioname));
this.PlayClip(sound, volume);
AudioDictionary[audioname]++;
}
}
}
else
{
AudioDictionary.Add(audioname, 1);
AudioClip sound = this.GetAudioClip(audioname);
if (sound != null)
{
StartCoroutine(this.PlayClipEnd(sound, audioname));
this.PlayClip(sound, volume);
AudioDictionary[audioname]++;
}
}
}
/// <summary>
/// 暫停
/// </summary>
/// <param name="audioname"></param>
public void SoundPause(string audioname)
{
if (this.LastAudioSource != null)
{
this.LastAudioSource.Pause();
}
}
/// <summary>
/// 暫停所有音效音樂
/// </summary>
public void SoundAllPause()
{
AudioSource[] allsource = FindObjectsOfType<AudioSource>();
if (allsource != null && allsource.Length > 0)
{
for (int i = 0; i < allsource.Length; i++)
{
allsource[i].Pause();
}
}
}
/// <summary>
/// 停止特定的音效
/// </summary>
/// <param name="audioname"></param>
public void SoundStop(string audioname)
{
GameObject obj = this.transform.Find("audioname").gameObject;
if (obj != null)
{
Destroy(obj);
}
}
/// <summary>
/// 設置音量
/// </summary>
public void BGMSetVolume(float volume)
{
if (this.BGMAudioSource != null)
{
this.BGMAudioSource.volume = volume;
}
}
/// <summary>
/// 播放背景音樂
/// </summary>
/// <param name="bgmname"></param>
/// <param name="volume"></param>
public void BGMPlay(string bgmname, float volume = 1f)
{
BGMStop();
if (bgmname != null)
{
AudioClip bgmsound = this.GetAudioClip(bgmname);
if (bgmsound != null)
{
this.PlayLoopBGMAudioClip(bgmsound, volume);
}
}
}
/// <summary>
/// 暫停背景音樂
/// </summary>
public void BGMPause()
{
if (this.BGMAudioSource != null)
{
this.BGMAudioSource.Pause();
}
}
/// <summary>
/// 停止背景音樂
/// </summary>
public void BGMStop()
{
if (this.BGMAudioSource != null && this.BGMAudioSource.gameObject)
{
Destroy(this.BGMAudioSource.gameObject);
this.BGMAudioSource = null;
}
}
/// <summary>
/// 重新播放
/// </summary>
public void BGMReplay()
{
if (this.BGMAudioSource != null)
{
this.BGMAudioSource.Play();
}
}
#region 音效資源路徑
enum eResType
{
AB = 0,
CLIP = 1
}
/// <summary>
/// 下載音效
/// </summary>
/// <param name="aduioname"></param>
/// <param name="type"></param>
/// <returns></returns>
private AudioClip GetAudioClip(string aduioname, eResType type = eResType.CLIP)
{
AudioClip audioclip = null;
switch (type)
{
case eResType.AB:
break;
case eResType.CLIP:
audioclip = GetResAudioClip(aduioname);
break;
default:
break;
}
return audioclip;
}
private IEnumerator GetAbAudioClip(string aduioname)
{
yield return null;
}
private AudioClip GetResAudioClip(string aduioname)
{
return Resources.Load(ResourcePath + aduioname) as AudioClip;
}
#endregion
#region 背景音樂
/// <summary>
/// 背景音樂控制器
/// </summary>
/// <param name="audioClip"></param>
/// <param name="volume"></param>
/// <param name="isloop"></param>
/// <param name="name"></param>
private void PlayBGMAudioClip(AudioClip audioClip, float volume = 1f, bool isloop = false, string name = null)
{
if (audioClip == null)
{
return;
}
else
{
GameObject obj = new GameObject(name);
obj.transform.parent = this.transform;
AudioSource LoopClip = obj.AddComponent<AudioSource>();
LoopClip.clip = audioClip;
LoopClip.volume = volume;
LoopClip.loop = true;
LoopClip.pitch = 1f;
LoopClip.Play();
this.BGMAudioSource = LoopClip;
}
}
/// <summary>
/// 播放一次的背景音樂
/// </summary>
/// <param name="audioClip"></param>
/// <param name="volume"></param>
/// <param name="name"></param>
private void PlayOnceBGMAudioClip(AudioClip audioClip, float volume = 1f, string name = null)
{
PlayBGMAudioClip(audioClip, volume, false, name == null ? "BGMSound" : name);
}
/// <summary>
/// 循環播放的背景音樂
/// </summary>
/// <param name="audioClip"></param>
/// <param name="volume"></param>
/// <param name="name"></param>
private void PlayLoopBGMAudioClip(AudioClip audioClip, float volume = 1f, string name = null)
{
PlayBGMAudioClip(audioClip, volume, true, name == null ? "LoopSound" : name);
}
#endregion
#region 音效
/// <summary>
/// 播放音效
/// </summary>
/// <param name="audioClip"></param>
/// <param name="volume"></param>
/// <param name="name"></param>
private void PlayClip(AudioClip audioClip, float volume = 1f, string name = null)
{
if (audioClip == null)
{
return;
}
else
{
GameObject obj = new GameObject(name == null ? "SoundClip" : name);
obj.transform.parent = this.transform;
AudioSource source = obj.AddComponent<AudioSource>();
StartCoroutine(this.PlayClipEndDestroy(audioClip, obj));
source.pitch = 1f;
source.volume = volume;
source.clip = audioClip;
source.Play();
this.LastAudioSource = source;
}
}
/// <summary>
/// 播放玩音效刪除物體
/// </summary>
/// <param name="audioclip"></param>
/// <param name="soundobj"></param>
/// <returns></returns>
private IEnumerator PlayClipEndDestroy(AudioClip audioclip, GameObject soundobj)
{
if (soundobj == null || audioclip == null)
{
yield break;
}
else
{
yield return new WaitForSeconds(audioclip.length * Time.timeScale);
Destroy(soundobj);
}
}
/// <summary>
///
/// </summary>
/// <returns></returns>
private IEnumerator PlayClipEnd(AudioClip audioclip, string audioname)
{
if (audioclip != null)
{
yield return new WaitForSeconds(audioclip.length * Time.timeScale);
AudioDictionary[audioname]--;
if (AudioDictionary[audioname] <= 0)
{
AudioDictionary.Remove(audioname);
}
}
yield break;
}
#endregion
}
8常用方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GeneralMethod : UnitySingleton<GeneralMethod>
{
/// <summary>
/// 協程
/// </summary>
/// <param name="action">事件</param>
/// <param name="DelayTime">等待時間</param>
/// <returns></returns>
public IEnumerator Wait(Action action, float DelayTime)
{
yield return new WaitForSeconds(DelayTime);
action();
}
/// <summary>
/// 每隔一段時間執行一次
/// </summary>
/// <param name="timer">時間變量一般0開始</param>
/// <param name="timeKeep">時間間隔</param>
/// <param name="action">事件</param>
public void TimeInterval(ref float timer, float timeKeep, Action action)
{
timer += Time.deltaTime;
if (timer > timeKeep)
{
action();
timer = 0;
}
}
}
9.互動砸求的主要類首先導入TouchScript插件在EventSystem這個組件中依次掛入TouchScriptInputModule,Tuio Input,StandardInput,並且在Tuio Input中設置攝像機和雷達端口3333.
取消Physics Raycaster組件。創建一個plane。
實現腳本
using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using System.Collections.Generic;
using System;
using UniRx;
using DG.Tweening;
public class OnHit : MonoBehaviour, IPointerDownHandler
{
public GameObject hole;
public List<GameObject> GetSorce;
public int elephantHurtCount;
public int CJLHurtCount;
public changJL IP;
public changJL IP1;
Animator anim;
public AudioClip Hit;
public AudioClip SpaceHIt;
public AudioClip Mhit;
public AudioClip BigAnimal;
public AnimalManager manager;
public PaiHangBangCtrl over;
public AudioSource BG;
public AudioClip bg;
void Start()
{
}
// Update is called once per frame
void Update()
{
}
public void OnPointerDown(PointerEventData eventData)
{
CreatSpace(eventData.position);
CreatAnimal(eventData.position);
CreatDX(eventData.position);
CreatCJL(eventData.position);
CreatUI(eventData.position);
}
void CreatSpace(Vector3 pos)
{
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10000, 1 << 8))
{
return;
}
if (Physics.Raycast(ray, out hit, 10000, 1 << 12))
{
return;
}
if (Physics.Raycast(ray, out hit, 10000, 1 << 9))
{
//拍擊觸碰事件
GameObject clone = Pool.Instance.Spwan(Pool.Instance.prefabArray[0]);
clone.transform.position = hit.point;
clone.transform.parent = transform;
hit.transform.GetComponent<AudioSource>().clip = SpaceHIt;
hit.transform.GetComponent<AudioSource>().Play();
}
}
void CreatAnimal(Vector3 pos)
{
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10000, 1 << 8))
{
anim = hit.transform.parent.parent.GetComponent<Animator>();
anim.SetTrigger("disappear");
GameObject clone = Pool.Instance.Spwan(Pool.Instance.prefabArray[1]);
clone.transform.position = hit.point;
clone.transform.parent = transform;
//hit.transform.GetComponent<BoxCollider>().enabled = false;
StartCoroutine(BOX(hit));
if (hit.transform.parent.parent.name == "bama(Clone)")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = Hit;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[0], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); });
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Score.Score1 += 20;
}
if (hit.transform.parent.parent.name == "leopard@idle(Clone)")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = Hit;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[1], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); });
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Score.Score1 += 30;
}
if (hit.transform.parent.parent.name == "lacoste@idle(Clone)")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = Hit;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[2], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); });
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Score.Score1 += 40;
}
if (hit.transform.parent.parent.name == "Panda@idle(Clone)")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = Hit;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[3], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); });
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Score.Score1 += 60;
}
if (hit.transform.parent.parent.name == "IP01@idle(Clone)" || hit.transform.parent.parent.name == "IP02@idle(Clone)")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = Mhit;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[7], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); });
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Score.Score1 -= 30;
}
}
}
void CreatUI(Vector3 pos)
{
//Debug.Log("12222222");
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10000, 1 << 12))
{
//拍擊觸碰事件
//Debug.Log(hit.point);
GameObject clone = Pool.Instance.Spwan(Pool.Instance.prefabArray[1]);
clone.transform.position = hit.point;
clone.transform.parent = transform;
if (hit.transform.name == "Start")
{
hit.transform.GetComponent<AudioSource>().clip = Mhit;
hit.transform.GetComponent<AudioSource>().Play();
manager.OpenGame();
}
if (hit.transform.name == "over")
{
hit.transform.GetComponent<AudioSource>().clip = Hit;
hit.transform.GetComponent<AudioSource>().Play();
BG.GetComponent<AudioSource>().clip = bg;
BG.GetComponent<AudioSource>().Play();
over.againGame();
}
}
}
void CreatDX(Vector3 pos)
{
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10000, 1 << 8))
{
return;
}
if (Physics.Raycast(ray, out hit, 10000, 1 << 10))
{
elephantHurtCount += 1;
anim = hit.transform.parent.parent.GetComponent<Animator>();
GameObject Dx = hit.transform.parent.parent.gameObject;
GameObject clone = Pool.Instance.Spwan(Pool.Instance.prefabArray[1]);
clone.transform.position = hit.point;
clone.transform.parent = transform;
if (elephantHurtCount < 15)
{
anim.SetTrigger("disappear");
//anim.SetTrigger("hitback");
}
if (elephantHurtCount >= 15)
{
anim.SetTrigger("disappear");
anim.SetTrigger("die");
IP1.IPd();
Dx.transform.DOLocalMoveY(-250, 0.5f).SetEase(Ease.Linear).OnComplete(() =>
{
anim.SetTrigger("idle");
elephantHurtCount = 0;
});
}
if (hit.transform.parent.parent.name == "DaXiang@idle")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = BigAnimal;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[4], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); }); ;
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Observable.Timer(System.TimeSpan.FromSeconds(0.2f)).Subscribe(_ =>
{
GameObject fenClone1 = (GameObject)Instantiate(GetSorce[4], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone1.transform.DOMoveY(fenClone1.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone1); }); ;
//fenClone1.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
});
Observable.Timer(System.TimeSpan.FromSeconds(0.4f)).Subscribe(_ =>
{
GameObject fenClone2 = (GameObject)Instantiate(GetSorce[4], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone2.transform.DOMoveY(fenClone2.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone2); }); ;
//fenClone2.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
});
Score.Score1 += 60;
}
}
}
void CreatCJL(Vector3 pos)
{
Ray ray = Camera.main.ScreenPointToRay(pos);
RaycastHit hit;
if (Physics.Raycast(ray, out hit, 10000, 1 << 8))
{
return;
}
if (Physics.Raycast(ray, out hit, 10000, 1 << 11))
{
Debug.Log("次數" + CJLHurtCount);
CJLHurtCount += 1;
anim = hit.transform.parent.parent.GetComponent<Animator>();
GameObject CJL = hit.transform.parent.parent.gameObject;
GameObject clone = Pool.Instance.Spwan(Pool.Instance.prefabArray[1]);
clone.transform.position = hit.point;
clone.transform.parent = transform;
if (CJLHurtCount < 30)
{
anim.SetTrigger("disappear");
//anim.SetTrigger("hitback");
}
if (CJLHurtCount >= 30)
{
//Debug.Log("12312");
anim.SetTrigger("disappear");
anim.SetTrigger("die");
IP.IPd();
CJL.transform.DOLocalMoveY(-252, 0.5f).SetEase(Ease.Linear).OnComplete(() =>
{
anim.SetTrigger("idle");
CJLHurtCount = 0;
});
}
if (hit.transform.parent.parent.name == "ChangJingLu@idle")
{
hit.transform.parent.parent.GetComponent<AudioSource>().clip = BigAnimal;
hit.transform.parent.parent.GetComponent<AudioSource>().Play();
GameObject fenClone = (GameObject)Instantiate(GetSorce[5], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone.transform.DOMoveY(fenClone.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone); }); ;
//fenClone.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
Observable.Timer(System.TimeSpan.FromSeconds(0.3f)).Subscribe(_ =>
{
GameObject fenClone1 = (GameObject)Instantiate(GetSorce[5], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone1.transform.DOMoveY(fenClone1.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone1); }); ;
//fenClone1.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
});
Observable.Timer(System.TimeSpan.FromSeconds(0.6f)).Subscribe(_ =>
{
GameObject fenClone2 = (GameObject)Instantiate(GetSorce[5], new Vector3(hit.point.x, hit.point.y + 5, hit.point.z), Quaternion.Euler(new Vector3(0, 180, 0)));
fenClone2.transform.DOMoveY(fenClone2.transform.position.y + 20, 0.6f).OnComplete(() => { Destroy(fenClone2); }); ;
//fenClone2.GetComponent<SpriteRenderer>().material.DOFade(0, 0.8f).OnComplete(() => { Destroy(fenClone); });
});
Score.Score1 += 90;
}
}
}
IEnumerator BOX(RaycastHit hit)
{
hit.transform.GetComponent<BoxCollider>().enabled = false;
yield return new WaitForSeconds(2f);
if (hit.transform != null)
{
hit.transform.GetComponent<BoxCollider>().enabled = true;
}
}
}