Unity3DGame学习笔记(2)

来源:互联网 发布:像素设计软件 编辑:程序博客网 时间:2024/06/03 21:59

实验要求:

编程实践,请写步骤,贴代码并解释:

  • 写个用鼠标打飞碟的游戏。

  • 游戏要分多个 round , 飞碟数量每个 round 都是 n 个,但色彩,大小;发射位置,速度,角度,每次发射数量可以变化。

    游戏过程中,仅能创建 n 个飞碟, 且不容许初始化阶段生成任何飞碟。 飞碟线路计算请使用 mathf 类。 向下加速度 a 是常数。 飞碟被用户击中,则回收。并按你定义的规则计算分数。飞碟落地(y < c),则自动回收。

  • 请画 UML 图,描述主要对象及其关系。

实验效果:

代码UML图:


代码说明:

1.飞碟回收类工厂DiskFactory:

这个类主要是用来实现飞碟的资源管理,如生成飞碟,自动回收飞碟等。我在这里用List数组存储飞碟对象,方便管理。对外有三个函数可供调用,一个是getDisk获取飞碟对象,setDisk设置飞碟属性,DisableDisk用于回合更改时灭活还在Used里的飞碟。

using System.Collections;using System.Collections.Generic;using UnityEngine;public class DiskFactory : MonoBehaviour {//private static int MaxSize = 10;private SceneController Controller;private List<GameObject> Used;private List<GameObject> Free;// Use this for initializationvoid Awake () {Used = new List<GameObject> ();Free = new List<GameObject> ();Controller = SceneController.getControllerInstance ();Controller.setFactory (this);}
public void setDisk(Color c, float speed, float size, int t) {for (int i = 0; i < Free.Count; i++) {Free [i].GetComponent<DiskData> ().setDisk (c, speed, size, t);}for (int i = 0; i < Used.Count; i++) {Used [i].GetComponent<DiskData> ().setDisk (c, speed, size, t);}}// Update is called once per framevoid Update () {freeDisk ();}public void DisableDisk() {for (int i = 0; i < Used.Count; i++) {Used [i].SetActive (false);}}public GameObject getDisk() {GameObject temp;if (Free.Count != 0) {temp = Free [0];temp.SetActive (true);Free.RemoveAt (0);} else {temp = Instantiate (Resources.Load ("Prefabs/disk")) as GameObject;DiskData data = temp.GetComponent<DiskData> ();if (Controller.getRound() == 1)data.setDisk (Color.green, 0.5f, 1f, 1);else data.setDisk (Color.red, 0.7f, 0.8f, 2);temp.SetActive (true); }Used.Add (temp);return temp;}void freeDisk() {int R = Controller.getRound ();for (int i = 0; i < Used.Count; i++) {GameObject temp = Used [i];//Debug.Log (Used [i].transform.position.y);if (!Used [i].activeInHierarchy) {temp.SetActive (false);Used.RemoveAt (i);Free.Add (temp);} else if (Used [i].transform.position.y < 0.5f || Used [i].transform.position.z > 60f) {Controller.getRecorder ().lostScore (temp);temp.SetActive (false);Used.RemoveAt (i);Free.Add (temp);}}}}
2.场景控制类SceneController:

这个类主要用来注册工厂等功能类,注册有自己,Diskfactory和ScoreRecorder的实例,为了符合单例模式,调用其他功能类的单实例只能通过SceneController的get方法。里面有发射飞碟的方法emitDisk以及设置回合的方法NextRound和Round。

using System.Collections;using System.Collections.Generic;using UnityEngine;public class SceneController : System.Object {private static SceneController Controller_instance;private ScoreRecorder Recorder_instance;private DiskFactory Factory_instance;private int RoundNow = 0;Vector3 emitPos = new Vector3(-1.5f, 0.5f, 0.5f);Vector3 emitDir = new Vector3(10f, 50.0f, 67f);float emitSpeed = 0.5f;Color color;public static SceneController getControllerInstance () {if (Controller_instance == null) {Controller_instance = new SceneController();}return Controller_instance;}public ScoreRecorder getRecorder() {return Recorder_instance;}public void setRecorder(ScoreRecorder R) {Recorder_instance = R;}public DiskFactory getFactory() {return Factory_instance;}public void setFactory(DiskFactory F) {Factory_instance = F;}public void emitDisk() {GameObject temp = Factory_instance.getDisk();if (temp == null) {Debug.Log ("No disk, Please wait!");return;}temp.transform.position = emitPos;Debug.Log (temp.transform.position);Vector3 nextDir = emitDir;nextDir.x *= Random.Range (-4f, 4f);Debug.Log (emitDir * Random.Range (emitSpeed * 5, emitSpeed * 7) / 10);temp.GetComponent<Rigidbody>().AddForce (nextDir * Random.Range (emitSpeed * 5, emitSpeed * 7) / 10, ForceMode.Impulse);temp.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);}public void nextRound() {Factory_instance.DisableDisk ();if (RoundNow == 1) {RoundNow = 2;} else if (RoundNow == 2) {RoundNow = 1;} else {RoundNow = 1;}Round (RoundNow);}public void Round(int R) {Debug.Log ("Round = " + R);switch(R) {case 1:emitPos = new Vector3 (-1.5f, 0.5f, 0.5f);emitSpeed = 0.5f;color = Color.green;Factory_instance.setDisk (color, emitSpeed, 1f, 1);break;case 2:emitPos = new Vector3 (1.5f, 0.5f, 0.5f);emitSpeed = 0.7f;color = Color.red;Factory_instance.setDisk (color, emitSpeed, 0.8f, 2);break;}}public int getRound() {return RoundNow;}}
3.记分员类ScoreRecorder:

这个类主要用于飞碟计分工作,有两个方法,分别为得分getScore和失分lostScore,两个都根据飞碟的种类进行计分,不同种飞碟分值不同。

using System.Collections;using System.Collections.Generic;using UnityEngine;public class ScoreRecorder : MonoBehaviour {private SceneController Controller;private int Score;private int TotalScore;// Use this for initializationvoid Start () {Score = 0;TotalScore = 0;Controller = SceneController.getControllerInstance ();Controller.setRecorder (this);}// Update is called once per framevoid Update () {}public void getScore(GameObject d) {Score += 10 * d.GetComponent<DiskData> ().getType();Debug.Log (d.GetComponent<DiskData> ().getType ());TotalScore += 10 * d.GetComponent<DiskData> ().getType();if (Score >= 100) {Score = 0;Controller.nextRound ();}Debug.Log (Score);}public void lostScore(GameObject d) {Score -= 10 * d.GetComponent<DiskData> ().getType();TotalScore -= 10 * d.GetComponent<DiskData> ().getType();}public int returnScore() {return Score;}public int returnTScore() {return TotalScore;}}
4.飞碟数据类DiskData:

这个类主要用于记录和设置飞碟的相关属性,挂在飞碟的预制体上即可。

using System.Collections;using System.Collections.Generic;using UnityEngine;public class DiskData : MonoBehaviour {Color color;float speed;float size;int DiskType;public void setDisk(Color c, float sp, float s, int t) {color = c;speed = sp;size = s;DiskType = t;Debug.Log (this.name);this.GetComponent<MeshRenderer>().material.color = c;Debug.Log ("SetDisk");this.transform.localScale = new Vector3 (1f * size, 0.1f, 1f * size);}public int getType() {return DiskType;}}
5.用户交互类UserInterface:

这个类主要用于用户交互,界面的产生和处理点击操作在Update里处理。

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class UserInterface : MonoBehaviour {GameObject cam;Camera ca;float time = 0;public ParticleSystem explosion;public Text scoreText;public Text roundText;//public Text DiskNumText;public Text TotalScore;public Text TimeText;SceneController Controller;// Use this for initializationvoid Awake () {cam = GameObject.Find ("Camera");ca = cam.GetComponent<Camera> ();//explosion = Instantiate (Resources.Load ("Prefabs/explosion")) as ParticleSystem;Controller = SceneController.getControllerInstance ();Controller.nextRound ();}// Update is called once per framevoid Update () {if (Input.GetMouseButtonDown (0)) {Vector3 mp = Input.mousePosition;Ray ray = ca.ScreenPointToRay (Input.mousePosition);RaycastHit hit;if (Physics.Raycast (ray, out hit, Mathf.Infinity) && hit.collider.gameObject.tag == "Disk") {print ("I hit " + hit.transform.gameObject.name);hit.collider.gameObject.SetActive (false);PlayExplosion (hit.collider.gameObject);Controller.getRecorder ().getScore (hit.collider.gameObject);}}if (Input.GetKeyDown("space")) {Debug.Log ("Space Down");if (time <= 0) {time = 3;if (Controller.getRound () == 2) {Controller.emitDisk ();}Controller.emitDisk ();}}if (time > 0) {time -= Time.deltaTime;TimeText.text = "Next Disk Time : " + (int)(time + 0.5);} else {TimeText.text = "Disk Ready!";}scoreText.text = "TempScore : " + Controller.getRecorder ().returnScore ();roundText.text = "Round : " + Controller.getRound ();TotalScore.text = "TotalScore : " + Controller.getRecorder ().returnTScore ();}void PlayExplosion(GameObject t) {Debug.Log (explosion);explosion.transform.position = t.transform.position;explosion.GetComponent<Renderer>().material.color = t.GetComponent<Renderer>().material.color;explosion.Play ();}}
Unity资源设置:
首先创建一个底面plane,一个空对象Controller用于挂载脚本,将UserInterface,DiskFactory和ScoreRecorder挂上去。然后创建UI对象显示分数等,将每一个创建的Text拖进UserInterface的变量框里。坐标我是以(0,0,0)为基准,摄像机在(0,1,0)。

粒子对象的设置主要有






0 0
原创粉丝点击