unity3d 工厂类
游戏实践 无动作管理 打飞碟   
Hit UFO
无动作管理是因为飞碟的运动只需要
- 设置起点
 - 初速度
 - 启用重力
 
即可达到想要的效果(抛物线运动), 而后面两项需要用到组件 Rigidbody
, 当然设置在预设中就OK了, 就不必重复创建
上一下 FirstController 的代码, 十分简单..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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120// FirstController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mygame;
public class FirstController : MonoBehaviour, ISceneController, UserAction {
    public bool Playing;
    private int Round = 1;
    private float time = 0;
    private int DiskFlyOneTime;
    UserGUI userGUI;
    private Queue<GameObject> Disks = new Queue<GameObject>();
    private static int max = 9;
    private static int min = 2;
    private Vector3[] position = new Vector3[max];
    public DiskFactory Factory;
    // public CCActionManager actionManager;
    void Awake()
    {
        Director director = Director.GetInstance();
        director.CurrentScenceController = this;
        director.CurrentScenceController.LoadResources();
        userGUI = gameObject.AddComponent<UserGUI>() as UserGUI;
        for (int i = 0; i < max; i++)
        {
            position[i] = new Vector3(4-2*i, 4-2*i, -7);
        }
    }
    // 加载资源
    public void LoadResources()
    {
        
    }
    public void restart()
    {
        this.Round = 1;
        this.Playing = false;
        this.time = 0;
    }
    // 获取工厂单实例
    void Start () {  
        Factory = Singleton<DiskFactory>.Instance; 
    }
    
    // Update is called once per frame
    void Update () {  // 控制飞碟发出
        if (userGUI.status == 1)
        {
            if (time > 4f)
            {
                RoundOver();
            } else
            {
                time += Time.deltaTime;
                if (this.Playing == false)
                {
                    DiskFlyOneTime = Random.Range(min, max);
                    //Debug.Log(DiskFlyOneTime);
                    GameObject temp;
                    for (int i = 0; i < DiskFlyOneTime; i++)
                    {
                        //Debug.Log(Factory+"here");
                        temp = Factory.GetDisk(this.Round);
                        temp.transform.position = position[i];
                        temp.transform.GetComponent<Rigidbody>().velocity = temp.GetComponent<Disk>().direction * temp.GetComponent<Disk>().speed;
                        Disks.Enqueue(temp);
                    }
                    this.Playing = true;
                }
            }
        }
    }
    private void RoundOver() // 下一回合
    {
        while(Disks.Count > 0)
        {
            Factory.FreeDisk(Disks.Dequeue());
        }
        this.Round++;
        this.time = 0;
        this.Playing = false;
        if (Round > 10)
        {
            userGUI.status = 0;
        }
    }
    public void hit(Vector3 pos) // 点击发射射线打飞碟, 记录分数
    {
        Ray ray = Camera.main.ScreenPointToRay(pos);
        RaycastHit[] hits;
        hits = Physics.RaycastAll(ray);
        for (int i = 0; i < hits.Length; i++)
        {
            RaycastHit hit = hits[i];
            if (hit.collider.gameObject.GetComponent<Disk>() != null)
            {
                Debug.Log("hit");
                hit.collider.gameObject.SetActive(false);
                userGUI.Score += (0.1f * Round + 1) * (0.1f * Round + 1); 
                // 分数大约跟回合数的平方成正比
            }
        }
    }
}
还有本节课主要学习的内容, 工厂类
主要是因为频繁的创建和销毁对象会显著的降低性能, 所以我们可以把用完的游戏对象(GameObject)保留,
以便下一次需要时传递过去使用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// DiskFactory.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Mygame
{
    public class DiskFactory : MonoBehaviour
    {
        public GameObject DiskPrefab;// 读预制, 加快复制
        private List<GameObject> used = new List<GameObject>(); 
        // 存正在用的
        private List<GameObject> free = new List<GameObject>();
        // 存空闲的
        private void Awake() // 加载资源
        {
            DiskPrefab = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("DiskPrefab"), Vector3.zero, Quaternion.identity);
            DiskPrefab.SetActive(false);
        }
        public GameObject GetDisk(int Round)  //传递游戏对象给 FirstController
        {
            GameObject NewDisk = null;
            if (free.Count > 0)
            {
                NewDisk = free[0];
                free.Remove(free[0]);
            }
            else
            {
                NewDisk = GameObject.Instantiate<GameObject>(DiskPrefab, Vector3.zero, Quaternion.identity);
                NewDisk.name = NewDisk.GetInstanceID().ToString();
            }
            // 设置UFO难度
            NewDisk.GetComponent<Disk>().SetLevel(Round);
            return NewDisk;
        }
        public void FreeDisk(GameObject UsedDisk) // 将用完的对象回收
        {
            if (UsedDisk != null)
            {
                UsedDisk.SetActive(false);
                free.Add(UsedDisk);
                used.Remove(UsedDisk);
            }
        }
        // Use this for initialization
        void Start()
        {
        }
        // Update is called once per frame
        void Update()
        {
        }
    }
}
还有一个亮点的地方就是飞碟各种设置, 都是跟回合数有关的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// Disk.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace Mygame
{
    public class Disk : MonoBehaviour
    {
        public float size;
        public Color color;
        public float speed;
        public Vector3 direction;
        public void SetLevel(int Round = 1)  // 根据回合数设置数据
        {
            this.SetRandomSize(Round);
            this.SetRandomColor();
            this.SetRandomSpeed(Round);
            this.SetRandomDireation();
            this.gameObject.SetActive(true);
        }
        private void SetRandomColor()  // 随机颜色
        {
            float r = Random.Range(0f, 1f);
            float g = Random.Range(0f, 1f);
            float b = Random.Range(0f, 1f);
            this.color = new Color(r, g, b);
            this.gameObject.transform.GetComponent<Renderer>().material.color = this.color;
        }
        private void SetRandomSize(int Round = 1)  // 随机size, 是等比例的, (3.5,0.4,3.5)是我设置的预制的大小
        {
            float Level = 0.1f * (Round - 1) + 1;
            Level *= Level;
            this.size = Random.Range(0.7f / Level, 1f);
            this.gameObject.transform.localScale = (new Vector3(3.5f, 0.4f, 3.5f))*this.size;
            this.gameObject.transform.rotation = Quaternion.identity;
        }
        private void SetRandomSpeed(int Round = 1) // 随机速度, 同时决定了飞出去的方向
        {
            this.speed = Random.Range(4f,6f) * (0.09f * (Round - 1) + 1);
        }
        private void SetRandomDireation()
        {
            this.direction = new Vector3(Random.Range(-3.5f, 3.5f), Random.Range(2f, 3f), Random.Range(3f, 6f));
        }
    }
}
其他代码日后再贴
(一些关于分数统计的GUI, 导演类, 单实例模板类)