Unity學(xué)習(xí)記錄【二】

2020年9月18日
DFA算法過濾文本的敏感詞

  • Hashtable 的鍵值對可以是任何類型(均以object類為參數(shù))
  • 相關(guān)部門網(wǎng)站上會有敏感詞庫提供
  • 完成XML模板建立后,打開Excel可以自動映射成表格,然后擴(kuò)展完了之后

2020年9月19日
【事件?語法篇】如何聲明自定義的事件以及事件的完整/簡略聲明格式..

  • 事件是基于委托的,但事件不是委托類型。事件的本質(zhì)是委托字段的一個(gè)包裝器。既然是包裝器,那么就會在原有基礎(chǔ)上有更多限制。(在事件的完整聲明中就可以知道為什么了)

  • 為什么說事件是基于委托的?
    1.因?yàn)槲锌梢蕴峁?strong>強(qiáng)制類型兼容的語法
    2.因?yàn)槲锌梢?strong>存儲方法的引用

  • 事件在對委托的包裝上做出了哪些事?
    1.事件只能使用+=、-=,不能使用= (在委托中使用=符號,叫做Reset Invocation List,重置調(diào)用列表)
    2.事件的調(diào)用(OnXX.Invoke(...))只能在事件擁有者自身的觸發(fā)邏輯中調(diào)用,而委托可以在任意地方調(diào)用。
    *3.事件的簡略聲明格式中可以用==、!=來判斷是否為空,但是完整聲明格式里不行。

  • 事件的一般聲明方式
    一般在使用事件的時(shí)候,都是用public event EventHandler OnXX; 來定義的,
    其中EventHanlder這個(gè)類型是一個(gè)約定,代表所有訂閱OnXX的方法,都要滿足EventHandler的形式。

  • EventHandler的約定是void EventHandler(object sender, EventArgs e);它是一個(gè)委托類型。

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

//1.事件擁有者
//2.事件
//3.事件響應(yīng)者
//4.事件處理器
//5.訂閱

//1.我(類)要有一個(gè)事件(成員)
//2.一群別的類關(guān)心、訂閱我的事件(訂閱的時(shí)候要符合約定)   custom.OnOrder += waitor.TakeAction;
//3.我的事件發(fā)生了! (一定是由事件擁有者的內(nèi)部邏輯觸發(fā)的)    OnOrder.Invoke(this,e);
//4. 關(guān)心的類們被一次性通知到
//5. 被通知到的人,拿著事件參數(shù),做出相應(yīng)      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)   //在事件的完整聲明中,是不可以通過!=符號來判斷的,這里是個(gè)語法糖
        {
            OrderEventArgs e = new OrderEventArgs(coffeeName, coffeeBasePrice, cup);
            //事件觸發(fā)
            OnOrder.Invoke(this, e);
        }
       
    }

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

//事件響應(yīng)者
public class Waitor
{

    //事件處理器
    //按照自己的職責(zé)、任務(wù)做出特定處理
    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 +"點(diǎn)了一杯"+ 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;
}
  • 事件的完整聲明方式(機(jī)理)
    因?yàn)橹辉贑ustom中作了改變,所以只列出了Custom類。 事件的內(nèi)部機(jī)理可以和屬性的內(nèi)部機(jī)理比對著來理解。
public class Custom
{
    public Custom(string name)
    {
        Name = name;
    } 
    public string Name { get; set; }
    public float Bill { get; set; }
    
    //“事件是基于委托”這句話的核心↓↓↓
    public EventHandler orderEventHandler;  
    //orderEventHandler是一個(gè)委托類型的字段,而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);
            //事件觸發(fā)
            //完整聲明中,只能通過事件內(nèi)部的委托字段來執(zhí)行
            orderEventHandler(this, e);
        }
    }

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

2020年9月20日
委托與事件
通過事件來改善腳本通信
本次例子,假設(shè)有以下三個(gè)類:

  • Player : 會死亡
  • Achievements(成就) :在死亡1000次的時(shí)候觸發(fā)成就
  • UserInterface(用戶界面)這三個(gè) : 顯示Player死亡信息

笨辦法:

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

在這里相當(dāng)于是Player做了一件事情,就去主動調(diào)用其他類。

  • 這樣做會發(fā)生什么?
    后續(xù)當(dāng)游戲系統(tǒng)復(fù)雜了,Player里頭就會有一堆雜七雜八的引用。讓Player的功能代碼看起來不那么專一
    也會使得代碼復(fù)用性變差,如果想在其他項(xiàng)目復(fù)用Player代碼。首先得剔除所有無關(guān)引用,因?yàn)檫@些引用壓根不在新項(xiàng)目中。

  • 那怎么做?
    讓Player死亡時(shí)觸發(fā)一個(gè)事件去通知所有關(guān)注它死亡的類。
    因?yàn)?strong>監(jiān)聽player是否死亡,實(shí)際上是其他想知道這個(gè)消息的類的職責(zé)

  • 因此正確的代碼應(yīng)該如下:

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; // 取消訂閱
  }
}
  • 另外:關(guān)于public event 后面跟的兼容類型,除了.Net給定的EventHandler,還可以用Action / Action<T> / Action<T1,T2> 、Func<ReturnT> / Func<T1,ReturnT>或是自定義的委托類型來約束。
  • 還有在喚醒事件的時(shí)候,一定要實(shí)現(xiàn)判空。

2020年9月23日
使用事件制作3D自動開關(guān)門(附:3D人物移動和旋轉(zhuǎn),out輸出參數(shù),3D搭建使用的快捷鍵..

  • 選中相機(jī),Ctrl+Shift+F 相機(jī)角度自動變成Scene界面視角

  • 按住Ctrl拖拽會對其網(wǎng)格。網(wǎng)格與對齊捕捉設(shè)置:


    網(wǎng)格與對齊

    每次移動的單位
  • 按住V頂點(diǎn)對齊

  • 在這期視頻中找到了別的想要的,Tween系列插件——LeanTween

Tween 事實(shí)上就是一種數(shù)學(xué)庫
能夠讓使用者更加方便的處理數(shù)學(xué)動畫

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

也可以用鏈?zhǔn)綄懛?,設(shè)置運(yùn)動過程中的速度曲線。例如:

 LeanTween.moveLocalY( gameObject, 3.0f , 1.0f).setEaseInSine();
速度曲線表格
  • 在OnDisable或者OnDestroy中記得取消訂閱,不然會報(bào)錯,而且導(dǎo)致內(nèi)存過大。

  • 代碼中用枚舉類型定義一個(gè)字段的話,在Inspect界面會有下拉框。

  • Unity官方免費(fèi)插件——ProGrids,方便搭建場景

  • Universal Render Pipeline

  • Unity官方免費(fèi)插件——PostProcessing

2020年9月24日


2020年9月24日

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

  • 存入數(shù)據(jù)庫的時(shí)間,要用國際協(xié)調(diào)時(shí)區(qū)DataTime.UtcNow

...我還是從第一集開始看吧
委托第一集


最近在研究NLP,還有浮島星球的策劃,還有大創(chuàng)的一些事情。
女朋友在準(zhǔn)備研究生面試,明天就要開始了,默默支持一下,嘿嘿!


2020年9月28日


2020年10月16日
Unity 中制作虛擬搖桿


2020年10月18日


Model: 存數(shù)據(jù),一般都是定義一些數(shù)據(jù)字段(比如:用戶名稱、設(shè)備縮放比、貼圖材質(zhì)、也可以有數(shù)據(jù)庫增刪改查操作這樣的方法
View: 存放UI數(shù)據(jù)引用、事件監(jiān)聽
Control:實(shí)現(xiàn)業(yè)務(wù)邏輯功能,獲取Model的數(shù)據(jù),通知View層更新數(shù)據(jù)


// 以下說的都有點(diǎn)問題↓↓↓
// FIXUnityEvent中沒有封裝UnityAction字段

  • <封裝了UnityAction委托字段的UnityEvent> 和 <C#中以關(guān)鍵字形式存在的event的區(qū)別>

UnityEvent中包含AddListener(UnityAction call)方法,Button.onClick就是UnityEvent類型的。
在AddListener中,會將參數(shù)call對應(yīng)的函數(shù)引用,訂閱到該UnityEvent對象中。

//目前還沒找到AddListener內(nèi)部機(jī)理。
// ↑↑↑


依賴倒置原則:高層次的模塊不應(yīng)該依賴于低層次的模塊,兩者都應(yīng)該依賴于抽象接口。

題外話:
看到了評論區(qū)的爭辯有點(diǎn)意思:

題外話

我覺得兩個(gè)都說的挺對的,有時(shí)候我們需要事先預(yù)測一個(gè)需求的規(guī)模,也不是什么都要循規(guī)蹈矩。小的需求,做一個(gè)大的框架,確實(shí)要付出一些接口開發(fā)的成本。但是如果做的時(shí)候就考慮了后期要擴(kuò)展這個(gè)功能,就需要想清楚了。
還有博主在這篇文章里說的最后一段,也挺有意思:

講了這么多依賴倒置原則的優(yōu)點(diǎn),我們也來打擊一下大家,在現(xiàn)實(shí)世界中確實(shí)存在著必須依賴細(xì)節(jié)的事物,比如法律,就必須依賴細(xì)節(jié)的定義。 “殺人償命”在中國的法律中古今有之,那這里的殺人就是一個(gè)抽象的含義,怎么殺,殺什么人,為什么殺人,都沒有定義,只要是殺人就統(tǒng)統(tǒng)得償命,那這就是有問題了,好人殺了壞人,還要陪上自己的一條性命,這是不公正的,從這一點(diǎn)看,我們在實(shí)際的項(xiàng)目中使用依賴倒置原則時(shí)需要審時(shí)度勢,不要抓住一個(gè)原則不放,每一個(gè)原則的優(yōu)點(diǎn)都是有限度的,并不是放之四海而皆準(zhǔn)的真理,所以別為了遵循一個(gè)原則而放棄了一個(gè)項(xiàng)目的終極目標(biāo):投產(chǎn)上線和盈利。作為一個(gè)項(xiàng)目經(jīng)理或架構(gòu)師,應(yīng)該懂得技術(shù)只是實(shí)現(xiàn)目的的工具,惹惱了頂頭上司,設(shè)計(jì)做得再漂亮,代碼寫得再完美,項(xiàng)目做得再符合標(biāo)準(zhǔn),一旦項(xiàng)目虧本,產(chǎn)品投入大于產(chǎn)出,那整體就是扯淡!你自己也別想混得更好!


2020年10月19日

  • UnityEvent如果要帶參數(shù)的話需要通過泛型的方式——UnityEvent<T0>,但這里有個(gè)坑,就是這個(gè)泛型的UnityEvent是抽象類,因此需要自己再定義一個(gè)類,去繼承它。例如:
public class SelectContentEvent : UnityEvent<string>
 {
    //空
 }

還有一個(gè)和UnityEvent不一樣的點(diǎn)——在聲明事件中,需要new。例如:

public SelectContentEvent OnSelectContent = new SelectContentEvent();

2020年10月21日

  • 修改某些Unity組件的值的時(shí)候,要注意獲取的對象是引用,還是拷貝。
    例如在Render類中有一個(gè)屬性,它在get方法中做了處理,返回的是materials數(shù)組的一份拷貝。
        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封裝的類里頭,如果包含的屬性是數(shù)組,都會返回一份拷貝。如果需要修改數(shù)組中的元素,只能通過改變數(shù)組的入口地址(為數(shù)組整體賦值)。

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就業(yè)信息網(wǎng)頁:
https://connect.unity.com/jobs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容