要求

大作业要求:

制作一款特定技术应用小游戏,并提交技术报告。

  1. 内容(请参考以下技术主题,但不限于这些主题):
  • 运用手机拍若干全景图,贴到天空盒或球型天空,做一个简单校园漫游功能。
  • 粒子系统效果制作,必须带一个控制组件,控制粒子呈现效果。
  • UI系统制作,包括展开式公告牌,背包系统。不包括血条等简单应用。
  • DoTween 组件仿写与实践
  • 坦克大战,必须包含3D导航技术
  • Vuforia组件与AR游戏创作

历届师兄优秀作品参考:https://blog.csdn.net/pmlpml/article/details/72236930?spm=1001.2014.3001.5502

  1. 报告提交方式和要求:
  • 博客网站选择,推荐: 博客园、简书、csdn、gitee page等公共博客或静态网站平台。
  • 游戏效果展示,博客 GIF: 工具抠抠视频秀;游戏视频:3分钟,上传流媒体网站分享,如 bilibili 这类广告少的网站
  • 完整代码保存在 Gitee,GitHub,避免不重要细节放在博客之中
  • 尊重他人劳动,在最后给出参考的博客、教材等
  1. 提交时间:

DDL:2023.01.14日前。
如有特殊情况如中招、生病,请以保重身体为第一要务,合理安排提交日期。

  1. 成绩评价:
  • 游戏作品的新颖性、技术博客面向大众易读易懂性,占 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并将模型位置调成好如下

  • step4:脚本挂载如下(AR 模式下和ch07有点不同,所以如下挂载就行)

代码

  • 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;//加载音效文件,我把跳跃的音频文件命名为jumpshoot = Resources.Load<AudioClip>("music/shoot");//把音源music的音效设置为jumpmusic.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 initializationvoid 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 resumedCameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);}}
}

感想:

  • 因为全体缓考,所以自己也有更多时间完成大作业,选择了完成配置繁琐的AR大作业,因为课时不够,老师上课并没有介绍这个部分,全靠自学,说起来还踩了不少坑。不过踩坑之后,我发现自己对于每一个配置细节都非常清晰,也就有了上面这么多图片的配置介绍。
  • AR作业本可以选择看起来炫酷的模型,这样效果更惊艳,也无需更复杂的逻辑控制。但是我选择了制作一个简单的小游戏,这样也算是对整个学期学习内容的回顾了。
  • 本学期的Unity学习之路告一段落啦,从无法控制GmaeObject位置和移动的小白,到现在基本掌握编写小游戏,还尝试了AR的菜鸟,花了许多心血的,也从师兄师姐的博客中学习到很多东西,非常感恩。

链接:
github仓库
bilibili视频

final-期末大作业-制作AR射箭小游戏(Unity AR配置详细教程)相关推荐

  1. 【抖音小游戏】 Unity制作抖音小游戏方案 最新完整详细教程来袭【持续更新】

    前言 [抖音小游戏] Unity制作抖音小游戏方案 最新完整详细教程来袭[持续更新] 一.相关准备工作 1.1 用到的相关网址 1.2 注册字节开发者后台账号 二.相关集成工作 2.1 下载需要的集成 ...

  2. 数据结构与程序设计实践期末大作业(编一个小游戏)————笨鸟先飞(C语言)

    笨鸟先飞小游戏编程教学 对于这个游戏我做的比较粗糙,用一个圆球代替了小鸟,如果导致您觉得降低了逼格,请自行更改. 在写本小游戏前请先自行安装EGE图形库. 直接上代码,因为代码已经非常详细了. 视频讲 ...

  3. 安卓期末大作业——Android弹力球小游戏

    功能描述: 弹力球小游戏,使用AndEnginePhysicsBox2D游戏开发引擎开发,适合新手学习.搭建方法请看入门教程菜单中的androidstudio项目搭建教程.关于怎么实现的问题请不要问我 ...

  4. HTML5期末大作业:网站——卡通漫画游戏官方网页 (萌王) 13个页面 HTML+CSS+JavaScript ~ 学生HTML个人网页作业作品下载 ~ web课程设计网页规划与设计

    HTML5期末大作业:HTML5期末大作业:网站--卡通游戏官方网页 (萌王)HTML+CSS+JavaScript ~ 学生HTML个人网页作业作品下载 ~ web课程设计网页规划与设计 ~大学生个 ...

  5. HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(HTML+CSS)~动漫主题html5网页模板-HTML期末作业课程设计期末大作业动漫主题html5网页模板-html5网页设计源码...

    HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(DIV+CSS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量太多?没 ...

  6. HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(HTML+CSS)~动漫主题html5网页模板-HTML期末作业课程设计期末大作业动漫主题html5网页模板-html5网页设计源码

    HTML期末大作业课程设计~仿阴阳师游戏官网首页html模板(DIV+CSS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量太多?没 ...

  7. HTML5期末大作业:网站——卡通漫画游戏官方网页 (萌王) 13个页面 HTML+CSS+JavaScript ~ 学生HTML个人网页作业作品下载 ~ web课程设计网页规划与设计...

    HTML5期末大作业:HTML5期末大作业:网站--卡通游戏官方网页 (萌王)HTML+CSS+JavaScript ~ 学生HTML个人网页作业作品下载 ~ web课程设计网页规划与设计 ~大学生个 ...

  8. c语言大作业俄罗斯方块,VC++ 6.0 C语言实现俄罗斯方块详细教程

    今天把我之前写的大作业分享一下吧,并教你们如何实现,希望你们看了前面的教程也能自己写一个. 1.要先下载一个 graphics.h 的头文件来绘图. 2.初始化窗口:initgraph(x, y);这 ...

  9. 微信小程序期末大作业,体育新闻小程序

    新闻小程序 一个简单的新闻小程序,时候初学者学习使用. 下载链接:https://download.csdn.net/download/weixin_43474701/85383035 点我下载资源

最新文章

  1. Windows 系统下使用grep 命令
  2. cmd 修改文件属性
  3. Zookeeper 安装
  4. 设计模式:单例模式之懒汉式
  5. linux 运行msi文件是什么意思,查看Msi文件内容
  6. php 获取权限,php 获取权限列表函数_PHP教程
  7. Eclipse RCP使用SWT.EMBEDDED方式显示batik的svgCanvas后窗口最大化变白问题
  8. Visual C#常用函数和方法集汇总
  9. CAS+SSO原理浅谈
  10. asp.net 用户注册怎么判断用户名是否重复 ajax,AJAX_asp.net结合Ajax验证用户名是否存在的代码,1, 使用JavaScript js文件,验证 - phpStudy...
  11. asp.net 页面数据导入word模板
  12. P2799国王的魔镜
  13. oracle中kill session的方法
  14. 信号与系统2020参考答案(网络试卷)
  15. ubuntu命令行一键安装谷歌浏览器
  16. python中系统找不到指定文件怎么办_python 系统找不到指定的文件
  17. 【luogu CF1009F】Dominant Indices(长链剖分优化DP)
  18. 实现仿百度图片查看功能(点击缩略图放大效果)
  19. Feishu(飞书) 聊天机器人应用(3/3)- DevOps 机器人助手,管理 GitLab Issues,BOT 开源示例程序
  20. LIBSVM在Matlab下的使用和LIBSVM的matlab软件下README全文翻译

热门文章

  1. Python的四个挑战者:Swift、Go、Julia、R
  2. 计算机的CPU检测软件
  3. 语音助手APP测试点
  4. GO 语言实现设计模式【全】
  5. A8Jr的XP版驱动程序
  6. 前端开发工程师——面试题总结
  7. 程序员视角的计算机系统 2.1.7 布尔代数的介绍
  8. 使用underscore模块的template功能实现对HTML的数据注入+template实现数据注入(后面更新)
  9. 软工1816 · 团队现场编程实战(抽奖系统)
  10. 机器学习【西瓜书/南瓜书】--- 第1章绪论(学习笔记+公式推导)