做了许多的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;
}
}
}