Unity学习记录【二】

2020年9月18日
DFA算法过滤文本的敏感词

  • Hashtable 的键值对可以是任何类型(均以object类为参数)
  • 相关部门网站上会有敏感词库提供
  • 完成XML模板建立后,打开Excel可以自动映射成表格,然后扩展完了之后

2020年9月19日
【事件•语法篇】如何声明自定义的事件以及事件的完整/简略声明格式..

  • 事件是基于委托的,但事件不是委托类型。事件的本质是委托字段的一个包装器。既然是包装器,那么就会在原有基础上有更多限制。(在事件的完整声明中就可以知道为什么了)

  • 为什么说事件是基于委托的?
    1.因为委托可以提供强制类型兼容的语法
    2.因为委托可以存储方法的引用

  • 事件在对委托的包装上做出了哪些事?
    1.事件只能使用+=、-=,不能使用= (在委托中使用=符号,叫做Reset Invocation List,重置调用列表)
    2.事件的调用(OnXX.Invoke(...))只能在事件拥有者自身的触发逻辑中调用,而委托可以在任意地方调用。
    *3.事件的简略声明格式中可以用==、!=来判断是否为空,但是完整声明格式里不行。

  • 事件的一般声明方式
    一般在使用事件的时候,都是用public event EventHandler OnXX; 来定义的,
    其中EventHanlder这个类型是一个约定,代表所有订阅OnXX的方法,都要满足EventHandler的形式。

  • EventHandler的约定是void EventHandler(object sender, EventArgs e);它是一个委托类型。

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

//1.事件拥有者
//2.事件
//3.事件响应者
//4.事件处理器
//5.订阅

//1.我(类)要有一个事件(成员)
//2.一群别的类关心、订阅我的事件(订阅的时候要符合约定)   custom.OnOrder += waitor.TakeAction;
//3.我的事件发生了! (一定是由事件拥有者的内部逻辑触发的)    OnOrder.Invoke(this,e);
//4. 关心的类们被一次性通知到
//5. 被通知到的人,拿着事件参数,做出相应      TakeAction(object _sender, EventArgs _e)

public class EventExample_Pro : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Custom custom = new Custom("Jimmy");
        Waitor waitor = new Waitor();
        //订阅
        custom.OnOrder += waitor.TakeAction;
        
        custom.Order("抹茶星冰乐",25,"大杯");
        custom.Order("焦糖玛奇朵", 28, "超大杯");
        custom.PayBill();     
    }
}

//事件拥有者
public class Custom
{
    public Custom(string name)
    {
        Name = name;
    } 
    public string Name { get; set; }
    public float Bill { get; set; }
    public event EventHandler OnOrder;
    
    public void Order(string coffeeName, float coffeeBasePrice, string cup)
    {
        if (OnOrder != null)   //在事件的完整声明中,是不可以通过!=符号来判断的,这里是个语法糖
        {
            OrderEventArgs e = new OrderEventArgs(coffeeName, coffeeBasePrice, cup);
            //事件触发
            OnOrder.Invoke(this, e);
        }
       
    }

    public void PayBill()
    {
        Debug.Log(Name + "一共需要支付" + Bill);
    }
}

//事件响应者
public class Waitor
{

    //事件处理器
    //按照自己的职责、任务做出特定处理
    internal void TakeAction(object _sender, EventArgs _e)
    {
        Custom custom = _sender as Custom;
        OrderEventArgs e = _e as OrderEventArgs;
        float bill = 0;
        switch (e.CoffeeCup)
        {
            case "中杯":
                bill = e.CoffeeBasePrice;
                break;
            case "大杯":
                bill = e.CoffeeBasePrice + 3;
                break;
            case "超大杯":
                bill = e.CoffeeBasePrice + 6;
                break;
            default:
                Debug.Log("只能在中杯、大杯、超大杯里挑选");
                break;
        }
        custom.Bill += bill;
        Debug.Log(custom.Name +"点了一杯"+ e.CoffeeName+",需要支付" + bill);
    }
}


//事件消息
public class OrderEventArgs : EventArgs
{
    public OrderEventArgs(string name, float basePrice, string cup)
    {
        CoffeeName = name;
        CoffeeBasePrice = basePrice;
        CoffeeCup = cup;
    }
    public string CoffeeName;
    public float CoffeeBasePrice;
    public string  CoffeeCup;
}
  • 事件的完整声明方式(机理)
    因为只在Custom中作了改变,所以只列出了Custom类。 事件的内部机理可以和属性的内部机理比对着来理解。
public class Custom
{
    public Custom(string name)
    {
        Name = name;
    } 
    public string Name { get; set; }
    public float Bill { get; set; }
    
    //“事件是基于委托”这句话的核心↓↓↓
    public EventHandler orderEventHandler;  
    //orderEventHandler是一个委托类型的字段,而OnOrder事件是它的包装器
    //OnOrder是依赖于orderEventHandler的
    public event EventHandler OnOrder
    {
        add
        {
            orderEventHandler += value;
        }
        remove
        {
            orderEventHandler -= value;
        }
    }
    
    public void Order(string coffeeName, float coffeeBasePrice, string cup)
    {
        if (orderEventHandler != null)  
        {
            OrderEventArgs e = new OrderEventArgs(coffeeName, coffeeBasePrice, cup);
            //事件触发
            //完整声明中,只能通过事件内部的委托字段来执行
            orderEventHandler(this, e);
        }
    }

    public void PayBill()
    {
        Debug.Log(Name + "一共需要支付" + Bill);
    }
}
  • 另外EventHandler、Sender、EventArgs 都可以派生。

2020年9月20日
委托与事件
通过事件来改善脚本通信
本次例子,假设有以下三个类:

  • Player : 会死亡
  • Achievements(成就) :在死亡1000次的时候触发成就
  • UserInterface(用户界面)这三个 : 显示Player死亡信息

笨办法:

public class Player{
  void Die(){
    FindObjectOfType<Achievements>().OnPlayerDeath();
    FindObjectOfType<UIInterface>().OnPlayerDeath();
  }
}
public  class Achievements{
  public void OnPlayerDeath(){
  }
}
public  class UserInterface{
  public void OnPlayerDeath(){
  }
}

在这里相当于是Player做了一件事情,就去主动调用其他类。

  • 这样做会发生什么?
    后续当游戏系统复杂了,Player里头就会有一堆杂七杂八的引用。让Player的功能代码看起来不那么专一
    也会使得代码复用性变差,如果想在其他项目复用Player代码。首先得剔除所有无关引用,因为这些引用压根不在新项目中。

  • 那怎么做?
    让Player死亡时触发一个事件去通知所有关注它死亡的类。
    因为监听player是否死亡,实际上是其他想知道这个消息的类的职责

  • 因此正确的代码应该如下:

public class Player{
  public event Action deathEvent;   //通过事件来通知其他类
  void Die(){
    if( deathEvent != null){
      deathEvent();     //或者deathEvent.Invoke();
  }
}

public  class Achievements{
  void Start(){
    FindObjectOfType<Player>().deathEvent += OnPlayerDeath;  // 订阅
  }
  public void OnPlayerDeath(){
    // TODO Something ...
    // ....
    FindObjectOfType<Player>().deathEvent -= OnPlayerDeath; // 记得取消订阅
  }
}
public  class UserInterface{
  void Start(){
    FindObjectOfType<Player>().deathEvent += OnPlayerDeath;  // 订阅
  }
  public void OnPlayerDeath(){
    // TODO Something ...
    // ....
    FindObjectOfType<Player>().deathEvent -= OnPlayerDeath; // 取消订阅
  }
}
  • 另外:关于public event 后面跟的兼容类型,除了.Net给定的EventHandler,还可以用Action / Action<T> / Action<T1,T2> 、Func<ReturnT> / Func<T1,ReturnT>或是自定义的委托类型来约束。
  • 还有在唤醒事件的时候,一定要实现判空。

2020年9月23日
使用事件制作3D自动开关门(附:3D人物移动和旋转,out输出参数,3D搭建使用的快捷键..

  • 选中相机,Ctrl+Shift+F 相机角度自动变成Scene界面视角

  • 按住Ctrl拖拽会对其网格。网格与对齐捕捉设置:


    网格与对齐

    每次移动的单位
  • 按住V顶点对齐

  • 在这期视频中找到了别的想要的,Tween系列插件——LeanTween

Tween 事实上就是一种数学库
能够让使用者更加方便的处理数学动画

  • 在AssetStore中下载免费版的之后,就可以用了。例如:
 LeanTween.moveLocalY( gameObject, to , time);

也可以用链式写法,设置运动过程中的速度曲线。例如:

 LeanTween.moveLocalY( gameObject, 3.0f , 1.0f).setEaseInSine();
速度曲线表格
  • 在OnDisable或者OnDestroy中记得取消订阅,不然会报错,而且导致内存过大。

  • 代码中用枚举类型定义一个字段的话,在Inspect界面会有下拉框。

  • Unity官方免费插件——ProGrids,方便搭建场景

  • Universal Render Pipeline

  • Unity官方免费插件——PostProcessing

2020年9月24日


2020年9月24日

排序、DotTween、LeanTween、十大Array用法、富文本、模板方法

  • 存入数据库的时间,要用国际协调时区DataTime.UtcNow

...我还是从第一集开始看吧
委托第一集


最近在研究NLP,还有浮岛星球的策划,还有大创的一些事情。
女朋友在准备研究生面试,明天就要开始了,默默支持一下,嘿嘿!


2020年9月28日


2020年10月16日
Unity 中制作虚拟摇杆


2020年10月18日


Model: 存数据,一般都是定义一些数据字段(比如:用户名称、设备缩放比、贴图材质、也可以有数据库增删改查操作这样的方法
View: 存放UI数据引用、事件监听
Control:实现业务逻辑功能,获取Model的数据,通知View层更新数据


// 以下说的都有点问题↓↓↓
// FIXUnityEvent中没有封装UnityAction字段

  • <封装了UnityAction委托字段的UnityEvent> 和 <C#中以关键字形式存在的event的区别>

UnityEvent中包含AddListener(UnityAction call)方法,Button.onClick就是UnityEvent类型的。
在AddListener中,会将参数call对应的函数引用,订阅到该UnityEvent对象中。

//目前还没找到AddListener内部机理。
// ↑↑↑


依赖倒置原则:高层次的模块不应该依赖于低层次的模块,两者都应该依赖于抽象接口。

题外话:
看到了评论区的争辩有点意思:

题外话

我觉得两个都说的挺对的,有时候我们需要事先预测一个需求的规模,也不是什么都要循规蹈矩。小的需求,做一个大的框架,确实要付出一些接口开发的成本。但是如果做的时候就考虑了后期要扩展这个功能,就需要想清楚了。
还有博主在这篇文章里说的最后一段,也挺有意思:

讲了这么多依赖倒置原则的优点,我们也来打击一下大家,在现实世界中确实存在着必须依赖细节的事物,比如法律,就必须依赖细节的定义。 “杀人偿命”在中国的法律中古今有之,那这里的杀人就是一个抽象的含义,怎么杀,杀什么人,为什么杀人,都没有定义,只要是杀人就统统得偿命,那这就是有问题了,好人杀了坏人,还要陪上自己的一条性命,这是不公正的,从这一点看,我们在实际的项目中使用依赖倒置原则时需要审时度势,不要抓住一个原则不放,每一个原则的优点都是有限度的,并不是放之四海而皆准的真理,所以别为了遵循一个原则而放弃了一个项目的终极目标:投产上线和盈利。作为一个项目经理或架构师,应该懂得技术只是实现目的的工具,惹恼了顶头上司,设计做得再漂亮,代码写得再完美,项目做得再符合标准,一旦项目亏本,产品投入大于产出,那整体就是扯淡!你自己也别想混得更好!


2020年10月19日

  • UnityEvent如果要带参数的话需要通过泛型的方式——UnityEvent<T0>,但这里有个坑,就是这个泛型的UnityEvent是抽象类,因此需要自己再定义一个类,去继承它。例如:
public class SelectContentEvent : UnityEvent<string>
 {
    //空
 }

还有一个和UnityEvent不一样的点——在声明事件中,需要new。例如:

public SelectContentEvent OnSelectContent = new SelectContentEvent();

2020年10月21日

  • 修改某些Unity组件的值的时候,要注意获取的对象是引用,还是拷贝。
    例如在Render类中有一个属性,它在get方法中做了处理,返回的是materials数组的一份拷贝
        public Material[] materials { get; set; }
  • 在Render组件的API中有如下说明:

Render.materials:

Note that like all arrays returned by Unity, this returns a copy of materials array. If you want to change some materials in it, get the value, change an entry and set materials back.

  • Unity封装的类里头,如果包含的属性是数组,都会返回一份拷贝。如果需要修改数组中的元素,只能通过改变数组的入口地址(为数组整体赋值)。

Unity Connect不做了

Hi JimmyZou,

Today we’re announcing that on February 4, 2021, Unity Connect, our dedicated talent and sharing marketplace, will shut down. We’re proud of the community that rallied around Connect and we are inspired by the great sharing and discovery that came from it.

We want to make this transition as smooth as possible for everyone who uses Connect. If you are an active user on the platform, click here to learn more about the alternatives that will be provided for some Connect features. If you would like to download any part of your profile, please feel free to do so before we delete your information on February 4, 2021.

Unity Connect就业信息网页:
https://connect.unity.com/jobs

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335