Crazy Learning for Day 20

1、C# 泛型的学习

我们习惯上把字段设置为私有的,这样外界不能修改字段的值,然后我们可以通过定义属性来设置和取得字段中的值。

private int age;
public int Age{//习惯上属性大写 字段小写
    set{
        if(value<0)return;
        age = value;
    }
    get{
        return age;
    }

2、虚方法

把一个基类函数声明为virtual,就可以在任何派生类中重写该函数:

class MyBaseClass{
        public virtual string VirtualMethod(){
            return "Method is called in base class";
        }
    }

在派生类中重写另外一个函数时,要使用override关键字显示声明

class MyDerivedClass:MyBaseClass{   
        public override string VirtualMethod(){
            return "Method is called in derivedclass.";
        }
    }

我们在子类里面重写虚函数之后,不管在哪里调用都是调用重写之后的方法

3、定义和实现接口

定义接口(飞翔功能)
    public interface IFlyHandler{
        public void Fly();
    }
实现接口
    public class Type1Enemy:IFlyHandler{
    }

定义一个接口在语法上跟定义一个抽象类完全相同,但不允许提供接口中任何成员的实现方式,一般情况下,接口只能包含方法,属性,索引器和事件的声明。
接口不能有构造函数,也不能有字段,接口也不允许运算符重载。
接口定义中不允许声明成员的修饰符,接口成员都是公有的

4、Unity 3D内存管理——对象池(Object Pool)

http://blog.csdn.net/ycl295644/article/details/47255273

使用Unity制作简单的对象池

当我们频繁创建删除大量对象的时候,对象的创建删除所造成的开销就不容小觑了。为了提高性能,我们往往需要实现一个对象池作为Cache:使用对象时,它从池中提取。用完对象时,它放回池中。从而减少创建对象的开销。

对象池技术基本原理:核心有两点,缓存和共享,即对于那些被频繁使用的对象,在使用完后,不立即将它们释放,而是将它们缓存起来,以供后续的应用程序重复使用,从而减少创建对象和释放对象的次数,进而改善应用程序的性能。事实上,由于对象池技术将对象限制在一定的数量,也有效地减少了应用程序内存上的开销。

实现一个对象池,一般会涉及到如下的类:

  • 对象池工厂(ObjectPoolFactory)类
    该类主要用于管理相同类型和设置的对象池(ObjectPool),它一般包含如下两个方法:
    一是创建特定类型和设置的对象池;CreatePool
    二是用于释放制定的对象池;destroyPool

同时为保证对象池共产的单一实现,可以采用singleton设计模式

public static ObjectPoolFactory getInstance() {
    if (poolFactory == Null)
        poolFactory = new ObjectPoolFactory();
    }
    return poolFactory;
}
  • 参数对象类(ParameterObject)
    该类主要用于封装所创建的对象池的一些属性参数,如池中可存放对象的数目的最大值、最小值等。

  • 对象池类(ObjectPool)
    用于管理要被池化对象的借出和归还,并通知PoolObjectFactory完成相应的工作。

  • 池化对象类(PoolableObjectFactory)
    该类主要负责管理池化对象的生命周期。

对于Unity来说,当游戏中需要发射子弹(gameobject)等操作的时候,不停的Instantiate 和 destroy就会很耗性能,如果又是多人游戏,那多人同时Instantiate和destroy子弹,配置不高的设备可能会炸,同时这种大量的创建和销毁是不必要的。

这里用对象池,就是说建立子弹对象的并使用完后不进行销毁,而是使用SetActive方法来改变其激活状态,等再次需要使用时再进行激活。这样的话,当创建进对象池的的对象足够多后就能实现循环利用而不是无限增加。

对于创建的字典,字典中的Key就对应于种类(手枪子弹或是机枪子弹),与key对应的是字典,也就是该种类的一个数组(手枪子弹1,手枪子弹2,……)

简单对象池实现

就是提前建立对象的一个列表,需要就取,不需要就放回池中。

Test.cs ObjectPool.cs Movement.cs(挂载在球上,作为obj)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPool : MonoBehaviour {


    public static ObjectPool instance;

    void Awake()
    {
        instance = this;
    }
    /// <summary>
    /// 对象
    /// </summary>
    public GameObject poolObj;

    /// <summary>
    /// 对象池容器
    /// </summary>
    private List<GameObject> poolObjs;

    /// <summary>
    /// 对象池大小
    /// </summary>
    public int initPoolSize = 5;

    /// <summary>
    /// 是否自动生成新的对象
    /// </summary>
    public bool isAutoGrow;

    void Start()
    {
        poolObjs = new List<GameObject>();

        for (int i = 0; i < initPoolSize; i++)
        {
            GameObject obj = Instantiate(poolObj);
            obj.SetActive(false);
            obj.transform.parent = transform;
            poolObjs.Add(obj); 
        }
    }

    public GameObject GetGameObject()
    {
        //从对象池中找到当前未激活的对象,将其返回给使用者
        for (int i = 0; i < poolObjs.Count; i++)
        {
            //当对象不是激活状态时进行的操作
            if (!poolObjs[i].activeSelf)
            {
                poolObjs[i].SetActive(true);
                return poolObjs[i];
            }
        }
        //当对象池大小不够的时候,自动添加
        if (isAutoGrow)
        {
            GameObject obj = Instantiate(poolObj);
            obj.transform.parent = transform;
            poolObjs.Add(obj);
            return obj;
        }

        return null;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

    private float timer;
    public float speed = 2f;

    void OnEnable()
    {
        transform.position = Vector3.zero;
        timer = 0; 
    }

    // Update is called once per frame
    void Update () {
        timer += Time.deltaTime;
        transform.Translate(Vector3.right * Time.deltaTime * speed);  

        if (timer > 2)
        {
            gameObject.SetActive(false);
            timer = 0;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            ObjectPool.instance.GetGameObject();
        }
    }
}

进阶对象池实现

http://www.manew.com/thread-101207-1-1.html

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 用于存储我们的对象池信息
/// </summary>
[System.Serializable]
public struct ObjectPoolInfo
{
    public GameObject obj;
    public int initPoolSize;
    public bool isAutoGrow;
}

public class ObjectPoolManager : MonoBehaviour {

    public static ObjectPoolManager instance;

    public ObjectPoolInfo[] ObjectPoolInfos;

    void Awake()
    {
        instance = this;
    }

    /// <summary>
    /// 对象池容器
    /// </summary>
    public Dictionary<string, ObjectPool> objectPools;

    void Start()
    {
        objectPools = new Dictionary<string, ObjectPool>();
        for (int i = 0; i < ObjectPoolInfos.Length; i++)
        {
            CreateObjectPool(ObjectPoolInfos[i].obj, ObjectPoolInfos[i].initPoolSize, ObjectPoolInfos[i].isAutoGrow);

        }
    }

    /// <summary>
    /// 创建对象池
    /// </summary>
    /// <param name="_obj"></param>
    /// <param name="_initPoolSize"></param>
    /// <param name="_isAutoGrow"></param>
    void CreateObjectPool(GameObject _obj, int _initPoolSize, bool _isAutoGrow)
    {

        if (objectPools.ContainsKey(_obj.name))
        {
            Debug.LogError("对象池已经存在!");
        }
        else
        {
            ObjectPool objectPool = new ObjectPool(_obj, _initPoolSize, _isAutoGrow);
            objectPools.Add(_obj.name, objectPool);
        }     
    }

    public GameObject GetGameObject(string objName)
    {
        return objectPools[objName].GetGameObject();
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ObjectPool {

    /// <summary>
    /// 对象
    /// </summary>
    public GameObject poolObj;

    /// <summary>
    /// 对象池容器
    /// </summary>
    private List<GameObject> poolObjs;

    /// <summary>
    /// 对象池大小
    /// </summary>
    public int initPoolSize = 5;

    /// <summary>
    /// 是否自动生成新的对象
    /// </summary>
    public bool isAutoGrow;

    //将原来的Start()改为初始化函数
    public ObjectPool (GameObject _obj, int initPoolSize, bool _isAutoGrow)
    {
        poolObjs = new List<GameObject>();

        poolObj = _obj;
        isAutoGrow = _isAutoGrow;

        for (int i = 0; i < initPoolSize; i++)
        {
            GameObject obj = GameObject.Instantiate(poolObj);
            obj.transform.parent = GameObject.FindWithTag("ObjectPoolManager").transform;
            obj.SetActive(false);
            poolObjs.Add(obj); 
        }
    }

    public GameObject GetGameObject()
    {
        //从对象池中找到当前未激活的对象,将其返回给使用者
        for (int i = 0; i < poolObjs.Count; i++)
        {
            //当对象不是激活状态时进行的操作
            if (!poolObjs[i].activeSelf)
            {
                poolObjs[i].SetActive(true);
                return poolObjs[i];
            }
        }
        //当对象池大小不够的时候,自动添加
        if (isAutoGrow)
        {
            GameObject obj = GameObject.Instantiate(poolObj);
            obj.transform.parent = GameObject.FindWithTag("ObjectPoolManager").transform;
            poolObjs.Add(obj);
            return obj;
        }

        return null;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Movement : MonoBehaviour {

    private float timer;
    public float speed = 2f;

    void OnEnable()
    {
        transform.position = Vector3.zero;
        timer = 0; 
    }

    // Update is called once per frame
    void Update () {
        timer += Time.deltaTime;
        transform.Translate(Vector3.right * Time.deltaTime * speed);  

        if (timer > 2)
        {
            gameObject.SetActive(false);
            timer = 0;
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Test : MonoBehaviour {

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            //ObjectPool.GetGameObject();
            ObjectPoolManager.instance.GetGameObject("Cube");
        }

        if (Input.GetMouseButtonDown(1))
        {
            //ObjectPool.GetGameObject();
            ObjectPoolManager.instance.GetGameObject("Sphere");
        }
    }
}

5、Unity技巧——使用单例模式Singleton

使用场景:你认为一些东西

在整个游戏中只有一个而你又想可以方便地

随时访问它,这时你就可以考虑单例模式。例如,你的游戏可能需要一个管理音乐播放的脚本,或者一个管理场景切换的脚本,或者一个管理玩家信息的通用脚本,又或者是管理游戏中各种常用UI的脚本。事实上,这些都是非常常用而且必要的。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值