这次的游戏比较简单,就不贴UML图啦
本游戏的两个资源都是asset store上的,都是免费的,分别搜索资源名就能找到啦。
AR和virtualbutton的配置就不再细说,具体可以参考TA的PPT,按部就班就可以完成。需要注意的事virtualbutton要放在识别图的范围内,而且大小和触碰的方法都要注意,不然很容易点了半天却没有点到。
小猫一共有三个状态,触碰按钮先根据其当前状态改变其状态,然后再在Updatea()中判断其状态,如果不在正确的位置就移动小猫的正确的位置。当然点击和释放按钮都要改变按钮的颜色,这样用户体验比较好。
public class VirtualButtonEventHandler : MonoBehaviour, IVirtualButtonEventHandler{
public enum CatState {LEFT, MIDDLE, RIGHT}
//for debug
public float catz;
//
private Vector3 toLf;
private Vector3 toRg;
public CatState cat_state = CatState.MIDDLE;
public GameObject cat;
public GameObject LfBtnCube;
public GameObject RgBtnCube;
public Animator ani;
public VirtualButtonBehaviour[] vbs;
// Use this for initialization
void Start () {
vbs = GetComponentsInChildren();
for (int i = 0;i < vbs.Length;i ++)
{
vbs[i].RegisterEventHandler(this);
}
ani.SetTrigger("Walk");
//color of buttons
LfBtnCube.GetComponent().material.color = Color.black;
RgBtnCube.GetComponent().material.color = Color.black;
toLf = new Vector3(-1, 0, 0);
toRg = new Vector3(1, 0, 0);
}
// Update is called once per frame
void Update () {
if (Director.GetInstance().playing)
{
//for debug
catz = cat.transform.position.z;
//move cat
if (cat_state == CatState.LEFT && cat.transform.position.z < 0.1f * 0.06f)
{
cat.transform.Translate(toLf * Time.deltaTime * 0.03f);
}
else if (cat_state == CatState.RIGHT && cat.transform.position.z > -0.1f * 0.06f)
{
cat.transform.Translate(toRg * Time.deltaTime * 0.03f);
}
else
{
if (cat.transform.position.z > 0)
{
cat.transform.Translate(toRg * Time.deltaTime * 0.03f);
}
else if (cat.transform.position.z < 0)
{
cat.transform.Translate(toLf * Time.deltaTime * 0.03f);
}
}
}
else
{
ani.ResetTrigger("Walk");
ani.SetTrigger("Idle");
}
}
public void OnButtonPressed(VirtualButtonAbstractBehaviour vb)
{
switch (vb.VirtualButtonName)
{
case "Lf":
Debug.Log("Lfpressed");
//change color of button
LfBtnCube.GetComponent().material.color = Color.yellow;
//change cat state
if (cat_state == CatState.MIDDLE) cat_state = CatState.LEFT;
else if (cat_state == CatState.RIGHT) cat_state = CatState.MIDDLE;
else cat_state = CatState.LEFT;
break;
case "Rg":
Debug.Log("Rgpressed");
//change color of button
RgBtnCube.GetComponent().material.color = Color.yellow;
//change cat state
if (cat_state == CatState.MIDDLE) cat_state = CatState.RIGHT;
else if (cat_state == CatState.LEFT) cat_state = CatState.MIDDLE;
else cat_state = CatState.RIGHT;
break;
}
}
public void OnButtonReleased(VirtualButtonAbstractBehaviour vb)
{
Debug.Log("released");
//ani.SetTrigger("Idle");
switch (vb.VirtualButtonName)
{
case "Lf":
//change color of button
LfBtnCube.GetComponent().material.color = Color.black;
break;
case "Rg":
//change color of button
RgBtnCube.GetComponent().material.color = Color.black ;
break;
}
}
}
新建一个轨道的子空物体,在上面根据轨道的不同类型挂上很多个trigger
当小猫碰撞trigger时将playing参数设为false即游戏结束,因为这次游戏的结构比较简单,playing就直接放在Director中,实现起来也比较方便
private void OnTriggerEnter(Collider other)
{
Director.GetInstance().playing = false;
Debug.Log("Die!!");
}
动作控制的话其实只有Idle和Walk两个动作,游戏进行时Walk,结束时Idle
if (Director.GetInstance().playing)
{
...
}
else
{
ani.ResetTrigger("Walk");
ani.SetTrigger("Idle");
}
因为ARcamera是跟着小猫的,所以让小猫移动其实有点麻烦,不如直接让轨道移动,因为没有其他参照物看起来就跟小猫移动是一样的
void Update () {
if(Director.GetInstance().playing)
this.transform.position = new Vector3(this.transform.position.x - 0.0008f, this.transform.position.y, this.transform.position.z);
}
实现的方法是使用两段轨道,一段走完走上下一段的时候把之前走完的那一段接在现在正在走的轨道后面,如此循环看起来就跟轨道走不完一样
public class TrackLoop : MonoBehaviour {
public float runningTrackx;
public GameObject track1;
public GameObject track2;
public GameObject runningTrack;
public GameObject preparingTrack;
private float positionLf;
private float positionRg;
// Use this for initialization
void Start () {
runningTrack = track1;
preparingTrack = track2;
positionLf = runningTrack.transform.position.x;
positionRg = preparingTrack.transform.position.x;
}
// Update is called once per frame
void Update () {
if (preparingTrack.transform.position.x <= positionLf)
{
Debug.Log("TrackLoop!!!");
runningTrack.transform.position = new Vector3(positionRg, runningTrack.transform.position.y, runningTrack.transform.position.z);
preparingTrack.transform.position = new Vector3(positionLf, preparingTrack.transform.position.y, preparingTrack.transform.position.z);
GameObject tmp = runningTrack;
runningTrack = preparingTrack;
preparingTrack = tmp;
}
}
}
这里是用了一个UI控件,然后游戏结束时SetActive(),就显示出来了
public class UserGUI : MonoBehaviour
{
//public GUISkin mySkin;
public GameObject UI;
void Start()
{
//GUI.skin = mySkin;
UI.SetActive(false);
}
void Update()
{
if (!Director.GetInstance().playing)
{
//GUI.Label(new Rect(400, 100, 800, 450), "GameOver");
UI.SetActive(true);
}
}
}
点击打开链接