2015-12-03 16:48:37 fenrir_sun 阅读数 951
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4715 人正在学习 去看看 张刚

Rect Transform

Rect Transform 是 2D 与 3D 图形元素空间位置组件,继承自transform(当手动移除后就会还原成transform)。主要用来设置UI界面中元素的大小、 位置和旋转。

这里写图片描述

锚点(anchor)锚点共有四个,分别与元素的四个角一一对应。对锚点简单的理解就是:有两个值时固定不变的,一个是锚点相对于父对象的百分比位置固定,一个是在本对象上四个锚点和元素的四个角的绝对距离固定。

轴(pivot)和UI本身的缩放与旋转有关,注意在旋转的时候,local模式与global模式有区别,local模式下边界就是UI图本身,而global模式下边界是沿着X,Y轴方向的,旋转后会大于元素图自身。UI本身的位置是相对于锚点的位置,会随着锚点的改变而改变。当四个锚点集中于一点时,posX/Y指的是锚点和轴之间的距离差,长和宽是UI元素自身的长宽;当锚点不集中于一点时,指的是UI元素边界和锚点上下左右的距离差。
由于锚点可以两两重合,因此也会出现一处是长宽,一处是距离差的情况。

锚点主要是用来做缩放的适应的,当元素的父节点改变尺寸时,元素会随着锚点的情况适应。
举例来说,当锚点和元素自身的四个角重合时,UI本身随着父对象的缩放成比例缩放,如果锚点固定在父对象的四个角上,则UI本身与父对象的边界距离固定。
这里写图片描述

Rotation是和原来的transform一样的,一般来说2D的UI中只要旋转Z轴就可以。

改变元素大小可以通过直接改变元素的width和height,或者改变元素的scale。区别是改变尺寸并不会改变UI子元素的大小,改变scale会改变内部所有的物件。scale可以设置为负值,即将元素反转,但是尺寸设为负值会使元素不可见。

另外Rect Transform有两种编辑模式可选:b(blueprint),r(raw)
就是右边的两个按钮,简单来说就是当改变尺寸时保持锚点不动还是元素不动。

blueprint模式可以在rect transform不被旋转和缩放下进行编辑,在此模式下UI元素不能旋转。此模式下更改anchor时,UI元素不会动而anchor和pivot会移动。
raw模式下改变anchor的值时,锚点和轴不会动而UI元素本身会动。
有一些UI组件(如layoutGroup)或父对象会影响rect transform值的调整。

2016-04-19 13:35:27 narutojzm1 阅读数 3978
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4715 人正在学习 去看看 张刚

我在做的是一个赛车游戏,里边元素比较多,有1000*1000的Terrain,有公路,有桥梁,有城市建筑,树木,花草。

在最开始只有Terrain和赛车的时候没有出现过内存溢出的问题,

我是用的赛车,就是标准资源包中的Car,

后面随着内容的丰富开始经常出现内存溢出,

经过检测,我发现,每次点击Car对象时,都高频率出现内存溢出,然后生成发布包时,加载场景时都很容易出现。于是我删除了Car,问题就没有再出现了。然后我换用了一些面数顶点数少的车模型来解决问题。

现在我来分析一下,为什么官方Car容易出现问题。

官方Car模型的数据如下:

Car

---SkyCarBody 34209 verts  || 59706 tris uv

---SkyCarComponents  43101 verts  || 64188 tris || 2 submeshes uv

---****** 3k         verts || 4k        tris

---****** 3k         verts || 4k        tris

---****** 3k         verts || 4k        tris

---****** 3k         verts || 4k        tris

---****** 3k         verts || 4k        tris

---****** 3k         verts || 4k        tris

... ...

Total: 100k  verts   || 130k    tris

官方Car做的非常细致,总计的点数、面数其实已经非常庞大了,但是对于一款简单的赛车游戏来说,实在是太多余,其实赛车简单的外壳和轮胎就足够了。


2019-07-30 20:43:40 weixin_43814599 阅读数 94
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4715 人正在学习 去看看 张刚

学习 Unity 3D游戏开发日常笔记(C# 第四周)、

2019.7.30(二)

目录

周二 周三 周三
数组传值相关 栈Stack 字典
ArrayList Queue队列 字典_练习
ArrayList增、删、查、插 练习 泛型 委托
集合ArrayList_排序 泛型集合List 委托可以当成一个变量进行传递:排序案例:
Hashtable 泛型集合List_练习 委托_事件
Hashtable 增、删、查 练习 观察者设计模式

数组传值相关

带ref:
在这里插入图片描述
不带ref:
在这里插入图片描述

ArrayList:

①可以动态增长的数组;
②可以自动扩展数组长度;
③增、删、查、改、插入数据;
④使用ArrayList需要引入using System.Collections;
1、
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、删除一个元素
在这里插入图片描述
在这里插入图片描述
3、根据元素下标号删除元素
在这里插入图片描述
在这里插入图片描述
4、从index位置开始删除count个元素
在这里插入图片描述
在这里插入图片描述
5、查找元素下标号
在这里插入图片描述
在这里插入图片描述
6、指定一个下标号插入一个元素
在这里插入图片描述
在这里插入图片描述
7、复制ArrayList中的数据到数组中
在这里插入图片描述
在这里插入图片描述
8、查、数组长度、数组中实际储存的数据数量
在这里插入图片描述
在这里插入图片描述

ArrayList增、删、查、插 练习:

using System.Collections;

namespace 集合ArrayList_练习
{
    public class Item {
        public int id;//唯一的
        public string name;
        public int count;

        public Item(int id, string name, int count)
        {
            this.id = id;
            this.name = name;
            this.count = count;
        }

        public override string ToString()
        {
            return string.Format("id:{0},名字:{1},数量:{2}", id, name, count);
        }
    }

    class BagDataManager {
        private static BagDataManager instance;
        public static BagDataManager Instance {
            get {
                if (instance == null) {
                    instance = new BagDataManager();
                }
                return instance;
            }
        }

        private BagDataManager() { }

        ArrayList itemList = new ArrayList();
        /// <summary>
        /// 向列表中添加装备,如果已经有了此种装备,只添加数量,不再重新添加
        /// </summary>
        /// <param name="item"></param>
        public void Add(Item item) {
            for (int i = 0; i < itemList.Count; i++)
            {
                Item item1 = ((Item)itemList[i]);
                if (item1.id == item.id) {
                    item1.count += item.count;
                    return;
                }
            }
            itemList.Add(item);
        }

        /// <summary>
        /// 删除一个元素
        /// </summary>
        /// <param name="item"></param>
        public void Remove(Item item) {
            for (int i = 0; i < itemList.Count; i++)
            {
                Item item1 = ((Item)itemList[i]);
                if (item1.id == item.id)
                {
                    itemList.Remove(item1);
                    return;
                }
            }
        }
        /// <summary>
        /// 根据一个id查找一个Item对象
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Item GetItem(int id) {
            for (int i = 0; i < itemList.Count; i++)
            {
                Item item = (Item)itemList[i];
                if (item.id == id) {
                    return item;
                }
            }
            return null;
        }
        /// <summary>
        /// 将一个Item对象数据插入到ItemList中,
        /// 如果;list中已经有了这个数据对象只修改数量
        /// </summary>
        /// <param name="item"></param>
        /// <param name="index"></param>
        public void Insert(Item item,int index) {
            for (int i = 0; i < itemList.Count; i++)
            {
                Item mItem = (Item)itemList[i];
                if (mItem.id == item.id) {
                    mItem.count += item.count;
                    return;
                }
            }

            itemList.Insert(index, item);
        }


        public void Show() {
            for (int i = 0; i < itemList.Count; i++)
            {
                Console.WriteLine(itemList[i].ToString());
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //Item:id 名字  数量
            //BagDataManager:增加  删  查  插
            Item item1 = new Item(101, "刀", 3);
            Item item2 = new Item(102, "刀2", 4);
            Item item3 = new Item(103, "刀3", 5);
            Item item4 = new Item(104, "刀4", 6);
            Item item5 = new Item(102, "刀2", 5);

            BagDataManager.Instance.Add(item1);
            BagDataManager.Instance.Add(item2);
            BagDataManager.Instance.Add(item3);
            BagDataManager.Instance.Add(item4);
            BagDataManager.Instance.Add(item5);

            //BagDataManager.Instance.Remove(item5);
            //Item item = BagDataManager.Instance.GetItem(103);
            // Console.WriteLine(item.ToString());

            //BagDataManager.Instance.Insert(item3, 2);

            BagDataManager.Instance.Show();

            Console.ReadLine();
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

集合ArrayList_排序:

using System.Collections;

namespace 集合ArrayList排序
{
    class Item : IComparable
    {
        public int id;
        public string name;
        public int atk;
        public int def;

        public Item(int id, string name, int atk, int def) {
            this.name = name;
            this.id = id;
            this.atk = atk;
            this.def = def;
        }

        public override string ToString()
        {
            return string.Format("id:{0} ,名字:{1},atk:{2},def:{3}", id, name, atk, def);
        }
        /// <summary>
        /// 当这个类实现了IComparable接口,ArrayList调用了Sort方法时
        /// 会自动调用此方法进行做对比,按照我们所设置的顺序进行排序
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public int CompareTo(object obj)
        {
            Item item = (Item)obj;
            if (def > item.def)
            {
                return -1;
            }
            else {
                return 1;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ArrayList al = new ArrayList();
            Item item1 = new Item(101, "刀", 200, 210);
            Item item2 = new Item(102, "刀2", 500, 180);
            Item item3 = new Item(103, "刀3", 300, 110);
            Item item4 = new Item(104, "刀4", 230, 140);
            Item item5 = new Item(105, "刀5", 100, 550);

            al.Add(item1);
            al.Add(item2);
            al.Add(item3);
            al.Add(item4);
            al.Add(item5);

            al.Sort();

            for (int i = 0; i < al.Count; i++)
            {
                Console.WriteLine(al[i].ToString());
            }

            Console.ReadLine();
        }
    }
}

在这里插入图片描述

Hashtable:

①using System.Collections;使用HashTable需要引入这个集合;
②键值在内存中时散列分布的;
③键值一一对应,键值可以多对一,不能一对多;
④键不能重复,但是值可以重复;
在这里插入图片描述
1、在这里插入图片描述
在这里插入图片描述
2、
在这里插入图片描述
3、
在这里插入图片描述
在这里插入图片描述

Hashtable 增、删、查 练习:

using System.Collections;

namespace 集合_HashTable练习
{
    public class Item
    {
        public int id;//唯一的
        public string name;
        public int count;

        public Item(int id, string name, int count)
        {
            this.id = id;
            this.name = name;
            this.count = count;
        }

        public override string ToString()
        {
            return string.Format("id:{0},名字:{1},数量:{2}", id, name, count);
        }
    }
    class BagDataManager {
        private static BagDataManager instance;
        public static BagDataManager Instance {
            get {
                if (instance == null) {
                    instance = new BagDataManager();
                }
                return instance;
            }
        }
        private BagDataManager() { }

        Hashtable itemTable = new Hashtable();

        /// <summary>
        /// 添加一个装备对象进哈希表
        /// </summary>
        /// <param name="item"></param>
        public void Add(Item item)
        {
            if (itemTable.ContainsKey(item.id))
            {
                //当前这个hashTable包含这个key,就可以根据这个key取到value
                //value是object类型的,需要强转成Item
                Item it = (Item)itemTable[item.id];
                it.count += item.count;
                //((Item)itemTable[item.id]).count += item.count;
            }
            else
            {
                itemTable.Add(item.id, item);
            }
        }

        /// <summary>
        /// 根据id(key)删除一个数据
        /// </summary>
        /// <param name="item"></param>
        public void Remove(Item item) {
            if (itemTable.ContainsKey(item.id)) {
                itemTable.Remove(item.id);
            }
        }
        /// <summary>
        /// 根据一个key值也就是id,查找当前id的装备
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public Item Find(int id){
            if (itemTable.ContainsKey(id)) {
                Item item = (Item)itemTable[id];
                return item;
            }
            return null;
        }
        
        public void Show() {
            foreach (var key in itemTable.Keys)
            {
                Item item = (Item)itemTable[key];
                Console.WriteLine(item.ToString());
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Item item1 = new Item(101, "刀", 3);
            Item item2 = new Item(102, "刀2", 4);
            Item item3 = new Item(103, "刀3", 5);
            Item item4 = new Item(104, "刀4", 6);
            Item item5 = new Item(102, "刀2", 5);

            BagDataManager.Instance.Add(item1);
            BagDataManager.Instance.Add(item2);
            BagDataManager.Instance.Add(item3);
            BagDataManager.Instance.Add(item4);
            BagDataManager.Instance.Add(item5);

            BagDataManager.Instance.Remove(item4);
            //查找到得数据是返回的引用类型,所以当前这个item和BageDataManager中的HashTable
            //存储的数据是指向堆中同一块区域,不能乱修改数据
            Item item = BagDataManager.Instance.Find(102);
            if (item != null) {
                //item.count = 100;      //查找到得数据是返回的引用类型,所以当前这个item和BageDataManager中的HashTable
                                         //存储的数据是指向堆中同一块区域,不能乱修改数据
                Console.WriteLine(item.id);
            }

            BagDataManager.Instance.Show();

            Console.ReadLine();
        }
    }
}

在这里插入图片描述

2019.7.30(二)

栈Stack

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

栈Stack_练习

using System.Collections;

namespace 集合_Stack_练习
{
    abstract class View {
        public abstract void Open();
        public abstract void Back();
    }

    class MainPanel : View
    {
        public string name;
        public MainPanel(string name) {
            this.name = name;
        }
        public override void Back()
        {
            Console.WriteLine("主界面返回");
            
        }

        public override void Open()
        {
            Console.WriteLine("打开主界面");
        }
    }
    class HeroPanel : View
    {
        public string name;
        public HeroPanel(string name)
        {
            this.name = name;
        }
        public override void Back()
        {
            Console.WriteLine("英雄界面返回");

        }

        public override void Open()
        {
            Console.WriteLine("打开英雄界面");
        }
    }

    class BagPanel : View
    {
        public string name;
        public BagPanel(string name)
        {
            this.name = name;
        }
        public override void Back()
        {
            Console.WriteLine("背包界面返回");

        }

        public override void Open()
        {
            Console.WriteLine("打开背包界面");
        }
    }

    class UIManager {
        private static UIManager instance;
        public static UIManager Instance {
           
            get
            {
                if (instance == null)
                {
                    instance = new UIManager();
                }
                return instance;
            }
        }

        private UIManager() { }

        Stack uiManager = new Stack();

        /// <summary>
        /// 新界面放入栈中
        /// </summary>
        /// <param name="view"></param>
        public void OpenView(View view) {
            uiManager.Push(view);
            OpenPeekView();
        }
        /// <summary>
        /// 返回一个界面
        /// </summary>
        public void BackView() {
            View v = (View)uiManager.Pop();
            v.Back();
            OpenPeekView();
        }
        /// <summary>
        /// 打开栈顶界面
        /// </summary>
        void OpenPeekView() {
            View v = (View)uiManager.Peek();
            v.Open();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            //利用栈实现功能,打开主界面--》英雄界面--》背包界面
            MainPanel mainPanel = new MainPanel("主界面");
            HeroPanel heroPanel = new HeroPanel("英雄界面");
            BagPanel bagPanel = new BagPanel("背包界面");

            UIManager.Instance.OpenView(mainPanel);
            UIManager.Instance.OpenView(heroPanel);
            UIManager.Instance.OpenView(bagPanel);

            UIManager.Instance.BackView();
            UIManager.Instance.BackView();

            Console.ReadLine();
        }
    }
}

在这里插入图片描述

Queue队列

在这里插入图片描述

泛型

在这里插入图片描述
类型替代的作用,可以先不定义具体数据类型,只处理具体逻辑,在调用方法时,编译器自动生成对应类型,这样减少了object的拆箱和装箱,提高了效率。

泛型的调用:

在这里插入图片描述

泛型类:

在这里插入图片描述
①虽然使用重载函数也能实现很多种数组的拷贝,但是不能实现所有类型数组的拷贝
②使用object也能达到效果,但是没有使用泛型效率高

总结:什么时候选择泛型?

①所有的逻辑跟数据类型不相关;
②除了数据类型不一样,其他逻辑都一样;

泛型集合List:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、
在这里插入图片描述
在这里插入图片描述
2、
在这里插入图片描述
在这里插入图片描述
3、
在这里插入图片描述
在这里插入图片描述
4、
在这里插入图片描述
在这里插入图片描述
5、
在这里插入图片描述
在这里插入图片描述
6、
在这里插入图片描述
在这里插入图片描述
7、
在这里插入图片描述

泛型集合List_练习:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 泛型集合_List练习2
{
    ////1、攻击优先,2、防御优先,3、血量优先
    enum PlayerSortType {
        AttackFirst = 1,
        DefFirst = 2,
        BloodFirst = 3,
        Reverse = 4,
    }

    class Monster : IComparable<Monster> {
        public string name;
        public int atk;
        public int def;
        public int blood;
        public Monster() {
            //this:当前对象、刚构建出来的对象
            MonsterManager.Instance.Add(this);
        }
        public Monster(string name) : this() {
            
            this.name = name;
        }
        public Monster(string name, int atk, int def, int blood) : this(name) {
            this.blood = blood;
            this.atk = atk;
            this.def = def;
        }

        public virtual void Attack() {
            Console.WriteLine("Monster 攻击方法");
        }

        public int CompareTo(Monster other)
        {
            PlayerSortType  type = MonsterManager.Instance.SortType;
            switch (type)
            {
                case PlayerSortType.AttackFirst:
                    if (other.atk > atk)
                    {
                        return 1;
                    }
                    else
                    {
                        return -1;
                    }
                case PlayerSortType.DefFirst:
                    if (other.def > def)
                    {
                        return 1;
                    }
                    else
                    {
                        return -1;
                    }
                case PlayerSortType.BloodFirst:
                    if (other.blood > blood)
                    {
                        return 1;
                    }
                    else
                    {
                        return -1;
                    }
                default:
                    return 0;
            }

            #region MyRegion
            //1、攻击优先,2、防御优先,3、血量优先
            //string input = MonsterManager.Instance.PlayerSelecetSort;
            //switch (input)
            //{
            //    case "1":
            //        if (other.atk > atk)
            //        {
            //            return 1;
            //        }
            //        else {
            //            return -1;
            //        }
            //    case "2":
            //        if (other.def > def)
            //        {
            //            return 1;
            //        }
            //        else
            //        {
            //            return -1;
            //        }
            //    case "3":
            //        if (other.blood > blood)
            //        {
            //            return 1;
            //        }
            //        else
            //        {
            //            return -1;
            //        }
            //    default:
            //        return 0;
            //} 
            #endregion


        }

        public override string ToString()
        {
            return string.Format("name:{0},atk:{1},blood:{2},def:{3}", name, atk, blood, def);
        }
    }
    class Goblin : Monster {
        public Goblin() { }
        public Goblin(string name) : base(name) { }
        public Goblin(string name, int atk, int def, int blood) : base(name,atk,def,blood) {
           
        }

        public override void Attack()
        {
            Console.WriteLine("哥布林:{0},在攻击",name);
        }
    }

    class Boss : Monster
    {
        public Boss() { }
        public Boss(string name) : base(name) { }

        public Boss(string name, int atk, int def, int blood) : base(name,atk,def,blood) {

        }
        public override void Attack()
        {
            Console.WriteLine("Boss:{0},在攻击", name);
        }
    }

    class MonsterManager {
        private static MonsterManager instance;
        public static MonsterManager Instance {
            get {
                if (instance == null) {
                    instance = new MonsterManager();
                }
                return instance;
            }
        }

        List<Monster> monsterList = new List<Monster>();

        /// <summary>
        /// 玩家选择的排序方式
        /// </summary>
        private string playerSelectSort = "1";
        public string PlayerSelecetSort {
            get {
                return playerSelectSort;
            }
            set {
                if (value == "1" || value == "2" || value == "3" || value == "4") {
                    playerSelectSort = value;
                }
            }
        }

        private PlayerSortType sortType;
        public PlayerSortType SortType {
            get {
                return sortType;
            }
            set {
                sortType = value;
            }
        }

        /// <summary>
        /// 将Monster的子类对象加入到列表中
        /// </summary>
        /// <param name="m"></param>
        public void Add(Monster m) {
            monsterList.Add(m);
        }

        public void AllAttack() {
            for (int i = 0; i < monsterList.Count; i++)
            {
                monsterList[i].Attack();
            }
        }
        /// <summary>
        /// 显示列表中所有元素
        /// </summary>
        public void Show() {
            if (sortType == PlayerSortType.Reverse) {
                monsterList.Reverse();
            }
            monsterList.Sort();
            for (int i = 0; i < monsterList.Count; i++)
            {
                Console.WriteLine(monsterList[i]);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            /*
             手动输入一组数(可任意长度),并对这个数列进行排序
	            每次提示用户输入:1,添加一个数字,2,排序并显示数列

             */

            #region MyRegion
            //List<int> list = new List<int>();
            //while (true)
            //{
            //    Console.WriteLine("请输入一个数字");
            //    string num_str = Console.ReadLine();
            //    int num;
            //    if (int.TryParse(num_str, out num))
            //    {
            //        list.Add(num);
            //    }
            //    list.Sort();
            //    for (int i = 0; i < list.Count; i++)
            //    {
            //        Console.WriteLine("第{0}个数字是:{1}", i, list[i]);
            //    }
            //} 
            #endregion

            /*
             书写一个怪物(Monster)类,在怪物类的构造中将其添加到一个静态列表,以怪物
            类做为基类派生Boss和Gablin类,遍历列表可以让Boss和Gablin的对象产生不同的
            攻击(多态)。
             */
            Monster goblin = new Monster("张三",1000,200,100);
            Monster boss = new Monster("王五",2000,150,80);
            Monster lisi = new Monster("李四", 1500, 260, 130);

            MonsterManager.Instance.Show();

            //MonsterManager.Instance.AllAttack();
            while (true) {
                Console.WriteLine("请选择排序规则:1、攻击优先,2、防御优先,3、血量优先,4,反转");
                string input = Console.ReadLine();
                int select;
                if (int.TryParse(input, out select)) {
                    // MonsterManager.Instance.PlayerSelecetSort = input;
                    if(select <5&& select>0)
                        MonsterManager.Instance.SortType = (PlayerSortType)select;
                }


                //将玩家输入的方式存在单例中
               

                MonsterManager.Instance.Show();
            }
            Console.ReadLine();
        }
    }
}

在这里插入图片描述

2019.8.1(四)

字典

字典在内存中时散列结构,使用Key值来对应Value值,对应HashTabel的泛型结构,不能通过索引值进行遍历。
在这里插入图片描述

字典添加元素的方法:

在这里插入图片描述
通过键访问字典的元素:注意中括号内的是键,而不是索引
在这里插入图片描述
字典的遍历:一般字典都是通过key来找到对应的Value值,很少进行遍历
在这里插入图片描述
KeyValuePair:键值对,成对出现的;

字典一般供人查询的,所以通过键查值用的比较多。
在这里插入图片描述
在这里插入图片描述

字典_练习

1、计算每个字母出现的次数“Welcome to HXSD!Welcome to Unity World!”
Dictionary<char, int> strDic = new Dictionary<char, int>();
string str = "Welcome to HXSD!Welcome to Unity World!";
char[] arr = str.ToArray();
for (int i = 0; i < arr.Length; i++)
{
    if (arr[i] == ' ' || arr[i] == '!')
        continue;

    if (strDic.ContainsKey(arr[i]))
    {
        strDic[arr[i]]++;
    }
    else
    {
        strDic.Add(arr[i], 1);
    }
}
foreach (var item in strDic.Keys)
{
    Console.WriteLine("strDic[{0}]:{1}", item, strDic[item]);
}

在这里插入图片描述

委托

委托(Delegate) 是存有对某个方法或多个方法引用的一种引用类型。
所有的委托(Delegate)都派生自 System.Delegate 类。

委托的声明:

在这里插入图片描述
声明的委托和被添加的方法函数签名要一致(参数数量,类型,返回值都必须一样);

委托的调用:

在这里插入图片描述

委托的注册和注销:

在这里插入图片描述

委托可以当成一个变量进行传递:排序案例:
namespace 委托_练习
{
    class Program
    {
        delegate void RingbellDele();
        delegate bool SortType(int x, int y);
        static void Main(string[] args)
        {
            /*
            写一个排序的方法,他可以指定不同的排序逻辑(委托、传参)
	        升序、降序、奇数在前、偶数在前

            把函数当前一个参数进行传递
            */
            Sort(EvenFirst);//选择排序方式

            Console.ReadLine();
        }
        /// <summary>
        /// 偶数在前
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        static bool EvenFirst(int x, int y) {
            if (x % 2 != 0 && y % 2 == 0)
            {
                return true;
            }
            else return false;
        }

        /// <summary>
        /// 奇数在前
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        static bool OddFirst(int x, int y) {
            if (x % 2 == 0 && y % 2 != 0)
            {
                return true;
            }
            else return false;
        }

        static bool Down(int x, int y) {
            return !Upper(x, y);
        }

        static bool Upper(int x, int y) {
            if (x > y)
            {
                return true;
            }
            else {
                return false;
            }
        }

        static void Sort(SortType sortType)
        {
            int[] arr = new int[30];
            Random r = new Random();
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i] = r.Next(0, 100);
            }

            for (int i = 0; i < arr.Length - 1; i++)
            {
                for (int j = 0; j < arr.Length - 1; j++)
                {
                    if (sortType(arr[j],arr[j+1]))
                    {
                        int temp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = temp;
                    }
                }
            }
            for (int i = 0; i < arr.Length; i++)
            {
                Console.WriteLine("arr[{0}]:{1}", i, arr[i]);
            }
        }
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

委托_事件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

泛型委托

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

观察者设计模式

namespace 观察者设计模式
{
    class Worker
    {
        public string name;
        public string doing;

        public Worker(string name,string doing) {
            this.name = name;
            this.doing = doing;
        }

        public void Notify() {
           
            Console.WriteLine("老板回来了,{0}快停止{1},开始干活",name,doing);
            doing = "在工作";
        }
    }

    delegate void NotifyDele();
    class Tongzhizhe {
        public string name;
        public Tongzhizhe(string name) {
            this.name = name;
        }
        NotifyDele notifyDele;

        public void Rigest(NotifyDele method) {
            if (notifyDele == null)
            {
                notifyDele = new NotifyDele(method);
            }
            else {
                notifyDele += method;
            }
        }

        public void BossBack() {
            notifyDele();
        }

    }
    class Boss {
        public string name;
        public Boss(string name){
            this.name = name;
        }

        public void WalkOut() {
            Console.WriteLine("老板外出了");
        }

        public void WalkBack() {
            Console.WriteLine("我{0}回来了",name);
        }

        public void Wandering(params Worker[] works) {
            for (int i = 0; i < works.Length; i++)
            {
                Console.WriteLine("{0},在{1}",works[i].name,works[i].doing);
            }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Boss huhansan = new Boss("胡汉三");
            huhansan.WalkOut();

            Worker zhangsan = new Worker("张三","炒股");
            Worker lisi = new Worker("李四", "看球赛");
            Worker wangwu = new Worker("王五", "玩游戏");

            Tongzhizhe tongzhizhe = new Tongzhizhe("童子哲");

            tongzhizhe.Rigest(zhangsan.Notify);
            tongzhizhe.Rigest(lisi.Notify);

            huhansan.WalkBack();

            tongzhizhe.BossBack();

            huhansan.Wandering(zhangsan, lisi, wangwu);

            Console.ReadLine();
        }
    }
}

在这里插入图片描述

2018-11-19 20:33:29 qq_41399543 阅读数 30
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4715 人正在学习 去看看 张刚

Unity3d优化

一、程序方面

01、务必删除脚本中为空或不需要的默认方法;

02、只在一个脚本中使用OnGUI方法;

03、避免在OnGUI中对变量、方法进行更新、赋值,输出变量建议在Update内;

04、同一脚本中频繁使用的变量建议声明其为全局变量,脚本之间频繁调用的变量或方法建议声明为全局静态变量或方法;

05、不要去频繁获取组件,将其声明为全局变量;

06、数组、集合类元素优先使用Array,其次是List;

07、脚本在不使用时脚本禁用之,需要时再启用;

08、可以使用Ray来代替OnMouseXXX类方法;

09、需要隐藏/显示或实例化来回切换的对象,尽量不要使用SetActiveRecursively或active,而使用将对象远远移出相机范围和移回原位的做法;

10、尽量少用模运算和除法运算,比如a/5f,一定要写成a*0.2f。

11、对于不经常调用或更改的变量或方法建议使用Coroutines & Yield;

12、尽量直接声明脚本变量,而不使用GetComponent来获取脚本; iPhone

13、尽量使用整数数字,因为iPhone的浮点数计算能力很差;

14、不要使用原生的GUI方法;

15、不要实例化(Instantiate)对象,事先建好对象池,并使用Translate“生成”对象;

二、模型方面

01、合并使用同贴图的材质球,合并使用相同材质球的Mesh;

02、角色的贴图和材质球只要一个,若必须多个则将模型离分离为多个部分;

02、骨骼系统不要使用太多;

03、当使用多角色时,将动画单独分离出来;

04、使用层距离来控制模型的显示距离;

05、阴影其实包含两方面阴暗和影子,建议使用实时影子时把阴暗效果烘焙出来,不要使用灯光来调节光线阴暗。

06、少用像素灯和使用像素灯的Shader;

08、如果硬阴影可以解决问题就不要用软阴影,并且使用不影响效果的低分辨率阴影;

08、实时阴影很耗性能,尽量减小产生阴影的距离;

09、允许的话在大场景中使用线性雾,这样可以使远距离对象或阴影不易察觉,因此可以通过减小相机和阴影距离来提高性能;

10、使用圆滑组来尽量减少模型的面数;

11、项目中如果没有灯光或对象在移动那么就不要使用实时灯光;

12、水面、镜子等实时反射/折射的效果单独放在Water图层中,并且根据其实时反射/折射的范围来调整;

13、碰撞对效率的影响很小,但碰撞还是建议使用Box、Sphere碰撞体;

14、建材质球时尽量考虑使用Substance;

15、尽量将所有的实时反射/折射(如水面、镜子、地板等等)都集合成一个面;

16、假反射/折射没有必要使用过大分辨率,一般6464就可以,不建议超过256256;

17、需要更改的材质球,建议实例化一个,而不是使用公共的材质球;

18、将不须射线或碰撞事件的对象置于IgnoreRaycast图层;

19、将水面或类似效果置于Water图层

20、将透明通道的对象置于TransparentFX图层;

21、养成良好的标签(Tags)、层次(Hieratchy)和图层(Layer)的条理化习惯,将不同的对象置于不同的标签或图层,三者有效的结合将很方便的按名称、类别和属性来查找;

22、通过Stats和Profile查看对效率影响最大的方面或对象,或者使用禁用部分模型的方式查看问题到底在哪儿;

23、使用遮挡剔除(Occlusion Culling)处理大场景,一种较原生的类LOD技术,并且能够“分割”作为整体的一个模型。

三、其它   场景中如果没有使用灯光和像素灯,就不要使用法线贴图,因为法线效果只有在有光源(Direct Light/Point Light/Angle Light/Pixel Light)的情况下才有效果。

2.1渲染

1.不使用或少使用动态光照,使用light mapping和light probes(光照探头)

2.不使用法线贴图(或者只在主角身上使用),静态物体尽量将法线渲染到贴图

3.不适用稠密的粒子,尽量使用UV动画

4.不使用fog,使用渐变的面片(参考shadow gun)

5.不要使用alpha –test(如那些cutout shader),使用alpha-blend代替

6.使用尽量少的material,使用尽量少的pass和render次数,如反射、阴影这些操作

7.如有必要,使用Per-Layer Cull Distances,Camera.layerCullDistances

8.只使用mobile组里面的那些预置shader

9.使用occlusion culling

11.远处的物体绘制在skybox上

12.使用drawcall batching: 对于相邻动态物体:如果使用相同的shader,将texture合并 对于静态物体,batching要求很高,详见Unity Manual>Advanced>Optimizing Graphics Performance>Draw Call Batching 规格上限

  1. 每个模型只使用一个skinned mesh renderer

  2. 每个mesh不要超过3个material

  3. 骨骼数量不要超过30

  4. 面数在1500以内将得到好的效率

2.2物理

1.真实的物理(刚体)很消耗,不要轻易使用,尽量使用自己的代码模仿假的物理

2.对于投射物不要使用真实物理的碰撞和刚体,用自己的代码处理

3.不要使用mesh collider

4.在edit->project setting->time中调大FixedTimestep(真实物理的帧率)来减少cpu损耗

2.3脚本编写

1.尽量不要动态的instantiate和destroy object,使用object pool

2.尽量不要再update函数中做复杂计算,如有需要,可以隔N帧计算一次

3.不要动态的产生字符串,如Debug.Log(“boo” + “hoo”),尽量预先创建好这些字符串资源

4.cache一些东西,在update里面尽量避免search,如GameObject.FindWithTag("")、GetComponent这样的调用,可以在start中预先存起来

5.尽量减少函数调用栈,用x = (x > 0 ? x : -x);代替x = Mathf.Abs(x)

6.String的相加操作,会频繁申请内存并释放,导致gc频繁,使用System.Text.StringBuilder代替

2.4 shader编写

1.数据类型 fixed / lowp - for colors, lighting information and normals, half / mediump - for texture UV coordinates, float / highp - avoid in pixel shaders, fine to use in vertex shader for position calculations.

2.少使用的函数:pow,sin,cos等

2.4 GUI

1.不要使用内置的onGUii函数处理gui,使用其他方案,如NGUI

3.格式

1.贴图压缩格式:ios上尽量使用PVRTC,Android上使用ETC

2016-01-06 19:18:00 weixin_33897722 阅读数 118
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4715 人正在学习 去看看 张刚

unity3d中让物体显示和隐藏的方法


  1. gameObject.renderer.enabled   
  2. //是控制一个物体是否在屏幕上渲染或显示  而物体实际还是存在的 仅仅是想当于隐身 而物体本身的碰撞体还依旧存在的  
  3.   
  4. GameObject.Destroy()    
  5. //表示移除物体或物体上的组件 代表销毁该物体  实际上该物体的内存并没有马上释放 而是在你下下个场景中槽释放内存资源,就是你a场景中Destroy了 通常是在c场景中才真正释放该物体的内存资源(这是我的体会 不知道理解错误没)  
  6.   
  7. gameObject.active     
  8. //是否在场景中停用该物体   在你gameObject.active =false中 则你在场景中用find找不到该物体    
  9. //假设该物体有子物体 你要用SetActiveRecursively(false) 来控制是否在场景中停用该物体(递归的)


记录下



using UnityEngine;
using System.Collections;

public class test : MonoBehaviour 
{
    GameObject m_obj;
	// Use this for initialization
	void Start () 
    {
        m_obj = GameObject.Find("box");
	}
	
	// Update is called once per frame
	void Update ()
    {
	
	}

    void OnGUI()
    {

        if (Input.GetKeyDown(KeyCode.W))
        {
           // m_obj.enabled = true;
            m_obj.SetActive(true);
        }

        if (Input.GetKeyDown(KeyCode.A))
        {
            m_obj.SetActive(false);
           // m_obj.enabled = false;
        }
    
    }
}


Unity-合集简介

阅读数 194

没有更多推荐了,返回首页