AR 版超级玛丽
本文将简要介绍下图这个 AR 小游戏的制作过程,完整项目可见 GitHub 仓库。原本还设计了一个复杂得多得游戏,碍于 Placenote 的各种奇怪的 Bug 而无法实现,希望以后能有更成熟的 AR SDK 出现。
首先用 Vuforia 插件的 Image Target
制作一个地板。由于涉及到图像识别,所以选择一个辨识度较高的杂志封面作为目标图像:
为 Image Target
创建一个 Plane 子对象,并添加草地的材质:
为了在地图上放置蘑菇,需要创建一个 Vuforia 中的 Ground Plane Stage
组件,并添加一个蘑菇子对象,表示在平面上创建蘑菇。然后再添加一个 Plane Finder
组件,并将 Content Positioning Behaviour
脚本中的 Anchor Stage
设置为刚刚创建的 Ground Plane Stage 对象,用于蘑菇的定位。结合这两个组件就能实现点击手机屏幕时在地面放置蘑菇。
在 Image Target
中添加一个马里奥对象,并创建四个虚拟按钮,分别用于控制马里奥的前进、后退、左转和右转。虚拟按钮默认是不显示的,此处用 Cube 对象为虚拟按钮添加外观:
为马里奥添加控制脚本,处理马里奥的移动及其与蘑菇的碰撞:
using UnityEngine;
public class MarioController : MonoBehaviour {
private enum MarioState {
Stop,
Forward,
Backward,
Left,
Right
};
private MarioState currentState;
private readonly float moveSpeed = 0.05f;
private readonly float turnSpeed = 80f;
private Animation idleAnimation;
private Animation runAnimation;
private void Start() {
idleAnimation = GetComponent<Animation>();
runAnimation = GetComponent<Animation>();
Stop();
}
private void Update() {
if (currentState == MarioState.Stop) {
return;
}
runAnimation.Play("run");
switch (currentState) {
case MarioState.Forward:
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
break;
case MarioState.Backward:
transform.Translate(Vector3.back * moveSpeed * Time.deltaTime);
break;
case MarioState.Left:
transform.Rotate(Vector3.up, -turnSpeed * Time.deltaTime);
break;
case MarioState.Right:
transform.Rotate(Vector3.up, turnSpeed * Time.deltaTime);
break;
}
}
public void MoveForward() {
currentState = MarioState.Forward;
}
public void MoveBackward() {
currentState = MarioState.Backward;
}
public void RotateLeft() {
currentState = MarioState.Left;
}
public void RotateRight() {
currentState = MarioState.Right;
}
public void Stop() {
idleAnimation.Play("idle");
currentState = MarioState.Stop;
}
private void OnCollisionEnter(Collision collision) {
if (collision.collider.gameObject.CompareTag("Meshroom")) {
Destroy(collision.collider.gameObject);
}
}
}
为 Image Target
添加虚拟按钮的处理脚本。当某个虚拟按钮被点击时,调用 MarioController 控制马里奥执行相应的动作。
using UnityEngine;
using Vuforia;
public class VirtualButtonEventHandler : MonoBehaviour, IVirtualButtonEventHandler {
public MarioController marioController;
private void Start() {
VirtualButtonBehaviour[] vbbs = GetComponentsInChildren<VirtualButtonBehaviour>();
foreach (VirtualButtonBehaviour vbb in vbbs) {
vbb.RegisterEventHandler(this);
}
}
public void OnButtonPressed(VirtualButtonBehaviour vb) {
switch (vb.VirtualButtonName) {
case "ForwardButton":
marioController.MoveForward();
break;
case "BackwardButton":
marioController.MoveBackward();
break;
case "LeftButton":
marioController.RotateLeft();
break;
case "RightButton":
marioController.RotateRight();
break;
}
}
public void OnButtonReleased(VirtualButtonBehaviour vb) {
marioController.Stop();
}
}
在 Unity 中构建 iOS 项目,在手机中启动该程序,然后将摄像头对准之前选用的杂志封面即可开始游戏:点击手机屏幕放置蘑菇,点击虚拟按钮移动马里奥。