Unity3DGame学习笔记(2)

实验要求:

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

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

  • 游戏要分多个 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 initialization
	void 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 frame
	void 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 initialization
	void Start () {
		Score = 0;
		TotalScore = 0;
		Controller = SceneController.getControllerInstance ();
		Controller.setRecorder (this);
	}
	
	// Update is called once per frame
	void 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 initialization
	void 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 frame
	void 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值