链接:
github仓库
bilibili视频
要求
大作业要求:
制作一款特定技术应用小游戏,并提交技术报告。
- 内容(请参考以下技术主题,但不限于这些主题):
- 运用手机拍若干全景图,贴到天空盒或球型天空,做一个简单校园漫游功能。
- 粒子系统效果制作,必须带一个控制组件,控制粒子呈现效果。
- UI系统制作,包括展开式公告牌,背包系统。不包括血条等简单应用。
- DoTween 组件仿写与实践
- 坦克大战,必须包含3D导航技术
- Vuforia组件与AR游戏创作
历届师兄优秀作品参考:https://blog.csdn.net/pmlpml/article/details/72236930?spm=1001.2014.3001.5502
- 报告提交方式和要求:
- 博客网站选择,推荐: 博客园、简书、csdn、gitee page等公共博客或静态网站平台。
- 游戏效果展示,博客 GIF: 工具抠抠视频秀;游戏视频:3分钟,上传流媒体网站分享,如 bilibili 这类广告少的网站
- 完整代码保存在 Gitee,GitHub,避免不重要细节放在博客之中
- 尊重他人劳动,在最后给出参考的博客、教材等
- 提交时间:
DDL:2023.01.14日前。
如有特殊情况如中招、生病,请以保重身体为第一要务,合理安排提交日期。
- 成绩评价:
-
游戏作品的新颖性、技术博客面向大众易读易懂性,占 60%
-
博客逻辑清晰,图文效果好,文字通顺, 占40%
-
有较好的 UML 设计图,可以适当提高评分等级
-
有较严重抄袭行为,要适当降低评分等级
-
评分成绩采用 10 分制。不设0.5分
配置Unity开发AR的环境
我参考的教程视频:这个教程比较短,需要细心看,另外他使用的Unity版本跟老师讲的不一样,请尽量使用跟教程同一个版本,或者参考老师给的教程
配置需要很多耐心,请做好准备!
多图预警!!!
配置Unity2019.3.9f1
- step1:请在Unity Hub中的install点击版本设置,如下
- step2:点击Add modules后,勾选如下的包并下载,下载较慢,需等待一段时间
创建项目,并配置项目内环境
-
step1:在项目中点击Windows -> Package Manage,勾选如下四个包,并下载(第二个包可能会在下载第一个包的时候自动下载)
-
step2:继续下载如下一个包,支持Vuforia
发布到手机的配置
可能前期配置有点长,但是请耐心细心的跟着做,不然很可能会踩坑噢…
- step1:手机配置,以华为手机为例,本机系统是鸿蒙2.0(亲测这里当安卓用是没问题的)
- step2:点击手机 设置 -> 关于手机,看到版本号,敲击八下后进入开发者模式,然后用USB将手机和电脑连接(这里记得选择文件传输)
- step3:回到Unity,选中左上角 File -> Buiding Settings
- step4:进入后选中Android,并点击右下角的switch platform转到安卓,并配置如下,注意Run Device选中你自己的手机设备,
- step5: 然后点击左下角的Player Settings,配置如下(主要是改一下红字的配置)
Vuforia数据库创建
最后一个前期工作啦!!!请耐心
- step1: 到Vudoria官网点击Develop(这里需要注册一个账号)
- step2: 点击右上角第一个按钮Get Basic,输入license Name然后确认
- - step3: 复制license key(下图红色块位置),然后点击Target Manager添加识别图
- step4:点击Add Database,然后输入DatabaseName点击Create
- step5:然后点击创建好的Database(上图中的ArrowShooting)进入如下界面
- step6:填好上面的内容,即创建了你的第一张AR识别图,然后点击Download Database下载两个文件Android Studio, Xcode or Visual Studio和Unity Editor
- step6:下载完之后将zip文件解压,解压完毕后如下,全部拖到项目中
- step7:点击import
开始我们的项目!
-
step1: 如下创建AR Camera
-
step2: 创建好之后,点击Open…这个按钮
-
step3: 将前面在Vuforia复制的license key黏贴到这个位置,我们的AR Camera就配置好啦!
(Tips:Max Simultaneous Trackes Images控制同时识别图的数量,我这里是3,根据需求设置) -
step4: 如下创建ImageTarget
-
step5: 创建好之后如下,选择刚刚从Vuforia下载的Database和你想要的识别图
- step6: 先将Perfabs拖到场景中确定好位置,再将Perfabs拖到ImageTareget下,这样就能顺利的使用AR的识别图功能啦
- step7: 点击File->Build And Run,这是你的手机需要与电脑用USB相连,然后就等待安装啦
- step8: 安装之后,拍摄你的识别图,效果如下
接下来是射箭小游戏!
-
step1: 按照我之前的博客 ch06-物理系统与碰撞——Arrowshooting射箭小游戏,配置各种预制件
-
step2:经过测试,在AR模式下,高速物体更容易穿模,所以Aroow的配置需做如下更改
-
首先将Head变大,比例如下,或者更大也可以,但是小心造成箭没击中靶,却停在空中的Bug
-
然后,将Head的材料变成如下,点击进去,一层一层选中
-
最后,点击Main Color,将颜色透明度选中到0,这样,这个用于碰撞的Head就变成透明的了
-
-
step3:创建两个ImageTarget并将模型位置调成好如下
文章来源:https://www.toymoban.com/news/detail-459373.html -
step4:脚本挂载如下(AR 模式下和ch07有点不同,所以如下挂载就行)
文章来源地址https://www.toymoban.com/news/detail-459373.html
代码
- action.cs: 这个跟ch07没有变化
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSAction : ScriptableObject
{
public bool enable = true;
public bool destroy = false;
public GameObject gameobject;
public Transform transform;
public ISSActionCallback callback;
protected SSAction() { }
public virtual void Start() { throw new System.NotImplementedException(); }
public virtual void Update() { throw new System.NotImplementedException(); }
public virtual void FixedUpdate() { throw new System.NotImplementedException(); }
}
public enum SSActionEventType : int { Started, Competeted }
public interface ISSActionCallback { void SSActionEvent(SSAction source, GameObject arrow = null); }
public class SSActionManager : MonoBehaviour, ISSActionCallback
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
protected void Update()
{
foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions)
{
SSAction ac = kv.Value;
if (ac.destroy) waitingDelete.Add(ac.GetInstanceID());
else if (ac.enable) ac.Update();
}
foreach (int key in waitingDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
DestroyObject(ac);
}
waitingDelete.Clear();
}
protected void FixedUpdate()
{
foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions)
{
SSAction ac = kv.Value;
if (ac.destroy) waitingDelete.Add(ac.GetInstanceID());
else if (ac.enable) ac.FixedUpdate();
}
foreach (int key in waitingDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
DestroyObject(ac);
}
waitingDelete.Clear();
}
public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager)
{
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add(action);
action.Start();
}
public void SSActionEvent(SSAction source, GameObject arrow = null)
{
if (arrow != null)
{
ArrowTremble tremble = ArrowTremble.GetSSAction();
this.RunAction(arrow, tremble, this);
}
else
{
Controllor scene_controller = (Controllor)SSDirector.GetInstance().CurrentScenceController;
}
}
}
public class ArrowFlyActionManager : SSActionManager
{
private ArrowFlyAction fly;
public Controllor scene_controller;
protected void Start()
{
scene_controller = (Controllor)SSDirector.GetInstance().CurrentScenceController;
scene_controller.action_manager = this;
}
public void ArrowFly(GameObject arrow, Vector3 wind, float holdTime)
{
fly = ArrowFlyAction.GetSSAction(wind, holdTime);
this.RunAction(arrow, fly, this);
}
}
public class ArrowFlyAction : SSAction
{
private float holdTime;
public Vector3 wind;
private ArrowFlyAction() { }
public static ArrowFlyAction GetSSAction(Vector3 wind, float holdTime_)
{
ArrowFlyAction action = CreateInstance<ArrowFlyAction>();
action.holdTime = holdTime_;
action.wind = wind;
return action;
}
public override void Update() { }
public override void FixedUpdate()
{
//加上风的力
this.gameobject.GetComponent<Rigidbody>().AddForce(wind*10, ForceMode.Force);
if (this.transform.position.z >=20 || this.gameobject.tag == "hit")
{
this.destroy = true;
this.callback.SSActionEvent(this, this.gameobject);
}
}
public override void Start()
{
Transform arrow = this.gameobject.transform;
arrow.GetComponent<Rigidbody>().isKinematic = false;
//这个是添加力的
arrow.GetComponent<Rigidbody>().AddForce((arrow.GetChild(0).position-arrow.position) * 40f * holdTime, ForceMode.Impulse);
arrow.SetParent(null);//解除父子关系
}
}
public class ArrowTremble : SSAction
{
float radian = 0;
float per_radian = 3f;
float radius = 0.01f;
Vector3 old_pos;
public float left_time = 0.8f;
private ArrowTremble() { }
public override void Start() { old_pos = transform.position; }
public static ArrowTremble GetSSAction()
{
ArrowTremble action = CreateInstance<ArrowTremble>();
return action;
}
public override void Update()
{
left_time -= Time.deltaTime;
if (left_time <= 0)
{
transform.position = old_pos;
this.destroy = true;
this.callback.SSActionEvent(this);
}
radian += per_radian;
float dy = Mathf.Cos(radian) * radius;
transform.position = old_pos + new Vector3(0, dy, 0);
}
public override void FixedUpdate() { }
}
- ArrowCollider.cs:基本上没有变化,只修改了分数,这个是挂载到ArrowHead上的脚本,用于检碰撞
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowCollider : MonoBehaviour
{
public Controllor scene_controller;
public scoreRecorder recorder;
void Start()
{
scene_controller = SSDirector.GetInstance().CurrentScenceController as Controllor;
recorder = singleton<scoreRecorder>.Instance;
}
void OnTriggerEnter(Collider c)
{
if (c.gameObject.name == "T1" || c.gameObject.name == "T2" || c.gameObject.name == "T3" || c.gameObject.name == "T4" || c.gameObject.name == "T5")
{
gameObject.transform.parent.gameObject.GetComponent<Rigidbody>().isKinematic = true;
gameObject.SetActive(false);
//Debug.Log(this.gameObject.transform.position);
float dis = Mathf.Sqrt(this.gameObject.transform.position.x * this.gameObject.transform.position.x + this.gameObject.transform.position.y * this.gameObject.transform.position.y);
float point = 0;
if (dis >= 0 && dis < 1) point = 5f;
else if(dis >= 1 && dis < 2) point = 4f;
else if(dis >= 2 && dis < 3) point = 3f;
else if(dis >= 3 && dis < 4) point = 2f;
else if(dis >= 4 && dis < 5) point = 1f;
//Debug.Log("集中了靶子:" + c.gameObject.name + " "+ point);
recorder.Record((int)Mathf.Floor(point));
}
}
}
- ArrowFactory.cs:这里改变了GetArrow这个函数,因为AR识别图的精度问题,将弓箭旋转后,脚本往往不能很好的添加弓箭到正确的位置,所以我提前在弓箭上挂载了20支箭,增加游玩体验感
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArrowFactory : MonoBehaviour
{
private GameObject arrow = null;
private GameObject AB = null;
private GameObject ImageTargetAB = null;
private List<GameObject> usingArrowList = new List<GameObject>();
private Queue<GameObject> unusedArrowList = new Queue<GameObject>();
public Controllor sceneControler;
private int arrownum = 0;
private List<GameObject> ArrowList = new List<GameObject>();
public void initiate(GameObject AB_,GameObject ImageTargetAB_)
{
AB = AB_;
ImageTargetAB = ImageTargetAB_;
}
private void Start()
{
GameObject a;
for(int i = 0; i < 20; i++)
{
a = GameObject.Find("Arrow (" + i + ")");
ArrowList.Add(a);
a.SetActive(false);
}
}
public GameObject GetArrow()
{
//还原工厂
//AB.transform.SetPositionAndRotation(new Vector3(0, 0, 0), Quaternion.Euler(0, 90, 0));
//AB.transform.localScale = new Vector3(1, 1, 1);
//if (unusedArrowList.Count == 0)
//{
// //arrow = Instantiate(Resources.Load<GameObject>("Prefabs/Arrow"));
// arrow = GameObject.Find("Arrow");
// Debug.Log("Arrow的位置:" + arrow.transform.position);
// Debug.Log("Arrow的角度:" + arrow.transform.rotation);
//}
//else
//{
// arrow = unusedArrowList.Dequeue();
// arrow.gameObject.SetActive(true);
//}
//arrow.transform.parent = AB.transform;
//arrow.transform.SetPositionAndRotation(ImageTargetAB.transform.position, Quaternion.Euler(ImageTargetAB.transform.rotation.x, ImageTargetAB.transform.rotation.y+90, ImageTargetAB.transform.rotation.z ));
//Debug.Log("Image的位置: " + ImageTargetAB.transform.position);
//Debug.Log("Image的角度: " + ImageTargetAB.transform.rotation);
//arrow.transform.localScale = new Vector3(1.6f, 1.6f, 1.6f);
//usingArrowList.Add(arrow);
//return arrow;
//因为AR识别的图片角度不精确,没有办法使用工厂模式动态添加Arrow,使用这种方式能更好的保证体验感
if (arrownum < 20)
{
arrow = ArrowList[arrownum];
arrow.SetActive(true);
arrownum++;
}
usingArrowList.Add(arrow);
return arrow;
}
public void FreeArrow()
{
for (int i = 0; i < usingArrowList.Count; i++)
{
if (usingArrowList[i].transform.position.y <= -15 || usingArrowList[i].transform.position.y >= 15)
{
usingArrowList[i].GetComponent<Rigidbody>().isKinematic = true;
usingArrowList[i].SetActive(false);
usingArrowList[i].transform.position = new Vector3(0, 0, 0);
unusedArrowList.Enqueue(usingArrowList[i]);
usingArrowList.Remove(usingArrowList[i]);
i--;
}
}
}
}
- Controllor.cs:这个也基本上跟ch07一样
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Controllor : MonoBehaviour, IUserAction, ISceneController
{
public scoreRecorder recorder;
public ArrowFactory arrow_factory;
public ArrowFlyActionManager action_manager;
public UserGUI user_gui;
SSDirector director;
private GameObject AB;
private GameObject arrow;
private GameObject target;
private GameObject ImageTargetAB;
private bool game_start = false;
private string wind = "";
private float wind_directX;
private float wind_directY;
public string GetScore() {
return recorder.getScore();
}
public string GetWind() {
return wind;
}
public void Restart() { SceneManager.LoadScene(0); }
public void BeginGame() { game_start = true; }
void Update() { if (game_start) arrow_factory.FreeArrow(); }
public void LoadResources() {
//找到场景中的弓和靶
target = GameObject.Find("target");
AB = GameObject.Find("AB");
ImageTargetAB = GameObject.Find("ImageTargetAB");//这个主要是控制弓箭的方向
}
public bool haveArrowOnPort() { return (arrow != null); }
void Start()
{
director = SSDirector.GetInstance();
director.CurrentScenceController = this;
LoadResources();
arrow_factory = singleton<ArrowFactory>.Instance;
arrow_factory.initiate(AB, ImageTargetAB);
recorder = gameObject.AddComponent<scoreRecorder>() as scoreRecorder;
user_gui = gameObject.AddComponent<UserGUI>() as UserGUI;
action_manager = gameObject.AddComponent<ArrowFlyActionManager>() as ArrowFlyActionManager;
}
public void create()
{
if (arrow == null)
{
wind_directX = Random.Range(-2f, 2f);
wind_directY = Random.Range(-2f, 2f);
CreateWind();
arrow = arrow_factory.GetArrow();
}
}
public void UpdateArrowPositioin()
{
arrow.transform.SetPositionAndRotation(ImageTargetAB.transform.position, Quaternion.Euler(ImageTargetAB.transform.rotation.x, ImageTargetAB.transform.rotation.y+90, ImageTargetAB.transform.rotation.z));
}
public void MoveBow(Vector3 fwd,float Xinput,float Yinput)
{
if (!game_start) { return; }
//这里就不直接用触屏移动弓箭了,使用AR的方式移动并旋转角度
//Vector3 vaxis = Vector3.Cross(fwd, Vector3.right);
//AB.transform.Rotate(vaxis, -Xinput * 5, Space.World);
//Vector3 haxis = Vector3.Cross(fwd, Vector3.up);
//AB.transform.Rotate(haxis, -Yinput * 5, Space.World);
}
public void Shoot(float holdTime)
{
if (game_start)
{
Vector3 wind = new Vector3(wind_directX, wind_directY, 0);
action_manager.ArrowFly(arrow, wind, holdTime);
//这里添加一个音效控件
arrow = null;
}
}
public void CreateWind()
{
string Horizontal = "", Vertical = "", level = "";
if (wind_directX > 0)
{
Horizontal = "西";
}
else if (wind_directX <= 0)
{
Horizontal = "东";
}
if (wind_directY > 0)
{
Vertical = "南";
}
else if (wind_directY <= 0)
{
Vertical = "北";
}
if ((wind_directX + wind_directY) / 2 > -0.5f && (wind_directX + wind_directY) / 2 < 0.5f)
{
level = "1 级";
}
else if ((wind_directX + wind_directY) / 2 > -1f && (wind_directX + wind_directY) / 2 < 1f)
{
level = "2 级";
}
else if ((wind_directX + wind_directY) / 2 > -1.5f && (wind_directX + wind_directY) / 2 < 1.5f)
{
level = "3 级";
}
else if ((wind_directX + wind_directY) / 2 > -2f && (wind_directX + wind_directY) / 2 < 2f)
{
level = "4 级";
}
wind = Horizontal + Vertical + "风" + " " + level;
}
}
- interface.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface ISceneController
{
void LoadResources();
}
public interface IUserAction
{
void MoveBow(Vector3 fwd, float Xinput, float Yinput);
void Shoot(float holdTime);
string GetScore();
void Restart();
string GetWind();
void BeginGame();
void create();
bool haveArrowOnPort();
void UpdateArrowPositioin();
}
- scoreRecorder .cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class scoreRecorder : MonoBehaviour
{
public int score;
void Start() { score = 0; }
public void Record(int point) {
score = point + score;
Debug.Log("scoreRecorder:" + score);
}
public string getScore()
{
return score.ToString();
}
}
- singleton.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class singleton<T> : MonoBehaviour where T : MonoBehaviour
{
protected static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = (T)FindObjectOfType(typeof(T));
if (instance == null)
{
Debug.LogError("An instance of " + typeof(T)
+ " is needed in the scene, but there is none.");
}
}
return instance;
}
}
}
- SSDirector .cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class : object
{
private static SSDirector _instance;
public ISceneController CurrentScenceController { get; set; }
public static SSDirector GetInstance()
{
if (_instance == null)
{
_instance = new SSDirector();
}
return _instance;
}
}
- UserGUI.cs:这里相比ch07添加了声音播放器,并且每1.3秒发射箭矢,20支箭得到50分即位获胜,否则失败,点击“重新开始”即可重新开始游戏
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UserGUI : MonoBehaviour
{
private IUserAction action;
GUIStyle style = new GUIStyle();
GUIStyle style2 = new GUIStyle();
GUIStyle style3 = new GUIStyle();
private bool game_start = false;
private float deltatime = 0;
public scoreRecorder recorder;
public AudioSource music;//音源AudioSource相当于播放器,而音效AudioClip相当于磁带
public AudioClip shoot;//这里我要给主角添加跳跃的音效
public Camera cam;
private float holdTime =0;
private int arrow_sum = 21;
void Start()
{
action = SSDirector.GetInstance().CurrentScenceController as IUserAction;
recorder = singleton<scoreRecorder>.Instance;
//给对象添加一个AudioSource组件
music = gameObject.AddComponent<AudioSource>();
//设置不一开始就播放音效
music.playOnAwake = false;
//加载音效文件,我把跳跃的音频文件命名为jump
shoot = Resources.Load<AudioClip>("music/shoot");
//把音源music的音效设置为jump
music.clip = shoot;
style.normal.textColor = new Color(0, 0, 0, 1);
style.fontSize = 32;
style2.normal.textColor = new Color(1, 1, 1);
style2.fontSize = 64;
style3.normal.textColor = new Color(1, 1, 1);
style3.fontSize = 32;
holdTime = 0;
cam = Camera.main;
}
void Update()
{
if (game_start)
{
if (action.haveArrowOnPort())
{
//更新箭的位置
//action.UpdateArrowPositioin();
//这里改成每2秒射击一次
deltatime += Time.deltaTime;
Vector3 fwd = cam.transform.forward;
fwd.Normalize();
if (deltatime >= 1.3)
{
//action.MoveBow(fwd, Input.GetAxis("Mouse X"), Input.GetAxis("Mouse Y"));
holdTime = deltatime;
action.Shoot(holdTime);
holdTime = 0;
deltatime = 0;
}
}
else if(arrow_sum>0)
{
deltatime += Time.deltaTime;
if (deltatime >= 0.5)
{
action.create();
deltatime = 0;
//播放音效
music.Play();
arrow_sum--;
}
}
}
}
private void OnGUI()
{
action = SSDirector.GetInstance().CurrentScenceController as IUserAction;
if (game_start)
{
GUI.Label(new Rect(10, 5, 200, 50), "风向: ", style);
GUI.Label(new Rect(10, 45, 200, 50), "分数:", style);
//GUI.Label(new Rect(10, 85, 200, 50), "力量:", style);
//Debug.Log("风&&&&&&&&&&&&&&&&&&" + action.GetScore());
GUI.Label(new Rect(90, 5, 200, 50), action.GetWind(), style);
//GUI.Label(new Rect(90, 45, 200, 50), action.GetScore(), style);
GUI.Label(new Rect(90, 45, 200, 50), recorder.score.ToString(), style);
//GUI.Label(new Rect(90, 85, 200, 50), holdTime.ToString(), style);
if (GUI.Button(new Rect(Screen.width - 200, 5, 200, 100), "重新开始") )
{
Time.timeScale = 1;
action.Restart();
return;
}
if (arrow_sum==0 && recorder.score >= 50)
{
GUI.Label(new Rect(Screen.width / 2 - 220, Screen.width / 2 - 300, 100, 100), "Congratulations!", style2);
Time.timeScale = 0;
}
else if (arrow_sum == 0 && recorder.score < 50)//射完了箭
{
GUI.Label(new Rect(Screen.width / 2 - 220, Screen.width / 2 - 300, 100, 100), "Please Try Again!", style2);
Time.timeScale = 0;
}
}
else
{
Time.timeScale = 1;
GUI.Label(new Rect(Screen.width / 2 - 220, Screen.width / 2 - 400, 100, 100), "Arrow Shooting", style2);
GUI.Label(new Rect(Screen.width / 2 - 180, Screen.width / 2 - 300, 100, 100), " 获得50分即游戏胜利!", style3);
if (GUI.Button(new Rect(Screen.width / 2 - 120, Screen.width / 2 - 150, 200, 100), "游戏开始"))
{
game_start = true;
action.BeginGame();
}
}
}
}
- clearCamera.cs:在场景中创建一个空的GameObject,并挂载clearCamera脚本会使摄像头更加清晰
using UnityEngine;
using System.Collections;
using Vuforia;
public class clearCamera : MonoBehaviour
{
// Use this for initialization
void Start()
{
VuforiaARController.Instance.RegisterVuforiaStartedCallback(OnVuforiaStarted);
VuforiaARController.Instance.RegisterOnPauseCallback(OnPaused);
}
void Update()
{
}
private void OnVuforiaStarted()
{
CameraDevice.Instance.SetFocusMode(
CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
private void OnPaused(bool paused)
{
if (!paused)
{ // resumed
// Set again autofocus mode when app is resumed
CameraDevice.Instance.SetFocusMode(
CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
}
}
}
感想:
- 因为全体缓考,所以自己也有更多时间完成大作业,选择了完成配置繁琐的AR大作业,因为课时不够,老师上课并没有介绍这个部分,全靠自学,说起来还踩了不少坑。不过踩坑之后,我发现自己对于每一个配置细节都非常清晰,也就有了上面这么多图片的配置介绍。
- AR作业本可以选择看起来炫酷的模型,这样效果更惊艳,也无需更复杂的逻辑控制。但是我选择了制作一个简单的小游戏,这样也算是对整个学期学习内容的回顾了。
- 本学期的Unity学习之路告一段落啦,从无法控制GmaeObject位置和移动的小白,到现在基本掌握编写小游戏,还尝试了AR的菜鸟,花了许多心血的,也从师兄师姐的博客中学习到很多东西,非常感恩。
到了这里,关于final-期末大作业-制作AR射箭小游戏(Unity AR配置详细教程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!