与游戏世界交互

Apr 17, 2018


编写一个简单的鼠标打飞碟(Hit UFO)游戏

Image text

游戏内容

游戏共分为6个round,难度递增

round1速度最慢,一次只发射一个disk;round2速度与round1相同,但每次发射两个disk

round3速度增加,每次发射一个disk,依次类推

disk速度共分三个等级,击中之后依次有1,2,4分

当得到一定的分数后,会自动到下一round,并立即增加两分

游戏架构

MVC架构,包含导演,场记。

门面模式, UserGUI类,但是GUI与场记分离得不彻底

动作分离,运用动作管理器,定义了break和emit动作

工厂模式, 使用DiskFactory来管理飞碟,运用了缓存,提高了性能

DiskFactory

这个工厂模式最突出的特点是它生产出disk后,用完之后也不删除,而是存起来,等下次使用的时候,重新设置下就可以使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  

public class DiskFactory {
	//单例模式
	private static DiskFactory _instance { get; set; }
	public static DiskFactory instance { get { if (_instance == null)  _instance = new DiskFactory(); return _instance; } }
	
	//保存正在使用的飞碟和空闲在缓存中的飞碟
	private List<GameObject> used = new List<GameObject>();
	private List<GameObject> free = new List<GameObject>();

	//通过调用此方法来获得一个飞碟
	public GameObject GetDisk(int round)
	{
		GameObject newDisk = null;

		//如果有空闲的飞碟,就取一个,返回
		if (free.Count > 0)
		{
			newDisk = free [0];
			free.Remove(free[0]);
		}
		//否则的话,克隆一个
		else  
		{
			newDisk = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/disk"), Vector3.zero, Quaternion.identity);
		}
		
		//随机地址
		newDisk.transform.position = new Vector3(Random.Range(-10f, 10f),5,0);
		
		//根据当前回合,设置颜色,大小
		switch (round)
		{
			case 1:  
			case 2:
				newDisk.transform.localScale = new Vector3 (3,0.5f,3);
				newDisk.GetComponent<Renderer>().material.color = Color.white;  
				break;  
			case 3:
			case 4:
				newDisk.transform.localScale = new Vector3 (2,0.4f,2);
				newDisk.GetComponent<Renderer>().material.color = Color.blue;  
				break;  
			case 5:
			case 6:
				newDisk.transform.localScale = new Vector3 (1,0.3f,1);
				newDisk.GetComponent<Renderer>().material.color = Color.black;  
				break;  
		}

		//添加到used的list中,并且激活
		used.Add(newDisk);  
		newDisk.SetActive(true);  
		return newDisk;  
	}  
	
	//将用完的飞碟回收,放到free的list中,等待下次使用
	public void FreeDisk(GameObject disk)
	{  
		foreach (var gb in used)  
		{  
			if (disk.GetInstanceID() == gb.GetInstanceID())  
			{  
				gb.SetActive (false);
				free.Add (gb);
				used.Remove (gb);
				break;
			}  
		}
	}  

}

编写一个简单的自定义 Component

目的

自定义Component及其GUI

效果

Image text Image text Image text

脚本

  • Disk.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Disk : MonoBehaviour {

	//飞碟的五个属性
	public float speed;
	public Vector3 size;
	public Vector3 position;
	public Vector3 direction;
	public Color color;

}
  • MyEditor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;
using UnityEditor;
using System.Collections;

[CustomEditor(typeof(Disk))] //自定义Disk的预览窗
public class MyEditor : Editor
{ 
	public override void OnInspectorGUI()
	{
		var target = (Disk)(serializedObject.targetObject); //构造序列化物体
		target.speed = EditorGUILayout.FloatField("SPEED",target.speed);
		target.size = EditorGUILayout.Vector3Field ("SIZE",target.size);
		target.position = EditorGUILayout.Vector3Field ("POSITION",target.position);
		target.direction = EditorGUILayout.Vector3Field ("DIRECTION",target.direction);
		target.color = EditorGUILayout.ColorField("COLOR",target.color);

	}

}

参考资料