2023年10月31日 星期二

UNITY

UNITY為遊戲ENGINE。底層:C++,透過OPENGL等協定,可跨平台使用PC MAC WII繪製畫面。與VR關係(待處理)。

Scene

windows->layout->default

運作都是由場景帶動,左側。場景內的物件都會顯示在畫面中,SCRIPT都會有start update的特性。

  • Main Camera,看到的部分就會變成Game的畫面(比例已經在Game設定)
    • 可調整大小
    • 可加入子物件(例如範例中的陷阱,是個靜態物件),會跟著攝影機移動
  • Canvas和Game視窗是兩個獨立項目,但最後會組合顯示
    • TEXT:Menu->GameObject->XX,畫面中最上面文字項目
    • BUTTON:Menu->GameObject->UI->button,產生出來的button自動就會進入canvas下。button可以隨意指定按下後,連結到某個一個script裡面的某一個function。如果這樣很好,按下後就可以在裡面找到位置最左邊或是第二,第三等等的項目。
  • 物件
    • (點著Scene) Menu->GameObject->Create Empty : 改名稱為"管理"
    • Add component  選擇new script,命名為GroundManager,點兩下編輯
    • 物件拷貝CTRL + D
    • 進階物件產生方式:先由BLENDER產生,再IMPORT。
    • 物件可以有父子關係。(例如範例內橫板有兩種)。
顯示,位置在中間,再細分成SCENE和GAME兩種,可按住後拖曳區分成不同區域(不是TAB)。拉到更邊邊還能變成長條狀。
  • SCENE(畫面安排)
    • 手(Q),移動整個場景scene。
    • 十(W),移動單一物件。
    • 圈(E),旋轉。
    • 方(R),比例縮放。
    • 方(T),大小縮放。
  • GAME(Camera看到畫面)
    • 可設定比例和解析度Free Aspect,若沒有中意可以按+,Aspect Ratio,名稱例如9:16
    • Camera和物件相似,可移動
    • 可Render。

Inspect,右側。

  • 點選左上角可以設定顏色,或是顯示與否
  • 中間區域可以設定位置大小
  • 點選add component。有很多可以加入,用搜尋可以找到需要的東西,或是最下面的Script。
  • 很奇特的是,所謂的component可以同時加入很多個,從物件導向的觀念來看,新生成的物件繼承自不同物件??
  • 碰撞(連結)
    • Box 2D,牆壁? 在X或是Y欄位,按住滑鼠拉動就會產生大小變化(和輸入數字一樣的效果)
    • Rigidbody 2D,準備要去碰撞的物品,例如玩家,在2D狀況下要鎖定Z軸,不然會旋轉constraints Z。所謂的鋼體概念很重要,就是移動時不是重新設定位置,而是加入力的概念
    • Circle Collider 2D,玩家?
    • rigidbody 剛體。物體就會有質量和引力等等,就會慢慢"往下掉",不用加入程式。
    • collider 碰撞範圍。例如box collider 2D。如果是碰撞,兩方物件都要設定。
  • 觸發動作,變成圖片sprite renderer,有個眼睛符號,可以加入內建的圖片。
Project,下方,包括影片、圖片、聲音、Script。
  • 預設為SampleScene,改名(F2或點進)
  • 可按右鍵新增物件
  • Create->2D->Sprites->Square。物件可以拖動到中間Scene之間。可以重複拖到中間,是產生新物建。
  • Create->Folder->Resources (會出現在Assets/Resources),這是保留字名稱。物件拉進入這個Resources之後,就變成Prefab,顏色是藍色。也可以重複拖到中間,狀態是"參考"。
  • 在Project中,新增一個C#檔案。把檔案拖曳到右邊物件編輯視窗,就會成為物件的一部分。
Console,下方
執行區,上方,三角形啟動,有明顯顏色切換,再按一次就取消。

概念

物件:
新物件:畫面中若需要控制新項目,最簡單的方法就是事先產生
物件屬性:當其他物體碰到就會觸發某種反應
物件變動:撰寫屬於物件的程式
公共資料:例如被射擊到要加分,就是系統變數,主要掌控的Manager
從概念上來說,要感覺場景改變有兩種方法,第一種是東西動(第一種下樓梯),第二種是camera動(第二種下樓梯)。
如果碰到牆壁,就把東西消失,然後繼續向後長,這樣應該很簡單。

Install、Environment

UNITY HUB:licence目前是個人用。

安裝版本2022,第一次開啟要等很久。

C#語言編輯器

  • 可使用VS Code或VS Community(若是蘋果或是LINUX應該是不同方案),我的環境是Community。
  • 連結方式為edit->preference->external tools->external script editor裡面。
  • C#中另外下載UNITY CODE SNIPPETS加快處理(連結)。
  • 儲存後回到UNITY會自動進行編譯,編譯結果在下方視窗
打包

C#

程式控制語言C#語言(聽說以前還支援Javascript)。(因為沒有特別提到需安裝WINDOWS VISUAL開發環境,但又能跨平台,推測應是內建C#編譯引擎)

  • Public的東西,在Inspect中可看到並且修改。(或是serializefield   private )
  • Debug.Break(); 會讓程式暫停
  • Debug.Log()
  • 讀取使用者輸入。
    • 左右移動。input.getkey(keycode.rightarrow)
  • 產生物件方法
    • 動態產生物件(連結)。GameObject newGround = Instantiate(Resources.Load<GameObject>("地板"));
  • transform.translate  會疊上去
  • 進階程式概念(連結)。
    • 因為是single thread,所以時間特別重要Time.deltatime
    • oncollisionenter2D 也會一直執行。
    • coroutines(連結  連結)。

資源

FB社團(連結)
初步範例,青蛙跳(中文) 連結
進階範例,TANK(英文),簡報內容 文字連結 文字連結 影片連結
有個找工作人的經歷和女兒類似 程式

2023年10月5日 星期四

XCODE & SWIFT & BLE

家裡老舊的蘋果mini 2012 late版本只能更新到10.13,無法使用XCODE。使用M1(13.6)下載XCODE版本15.0。

XCODE是IDE,對比於EClipse和Android Studio。基本操作語言為swift(類比於JAVA或Kotlin)。專案分成兩種,可開新專案,TAB選擇IOS,下面跳出Application和LIB兩大類,選擇Application類的第一項APP(連結)。
  • Product Name : HelloWorld
  • Team : skip
  • Organization : com.xxx
  • Bundle Identifier : 送審使用,先不用管
  • Interface : Storyboard,Xcode支援兩種 UI 建構方式Storyboard和SwiftUI
  • Language : Swift,Xcode支援 Objective-C 與 Swift
  • Use Core Data : 資料庫先不管
  • Include Tests : 測試先不管
或是開啟舊專案。如下載github的zip解壓縮,範例(連結)。對於從零開始寫IOS程式很有用(GITHUUB)。副檔名是xcodeproj。功能是按鈕直接傳送資料,收到回應後顯示在TEXTBOX內。

畫面

最基本的StoryBoard,UI入口為Main(介面編輯器)。點選右上方的加號,跳出元件選單。選擇Button拉到白色畫面中間,預設的名稱是Button,從右邊選單更改名稱為Hello World。右側選單還有非常多更新介面例如顏色等等的功能。

按鈕按下後,會帶動程式,程式在哪裡呢?因為APP模板預設有View對應架構,只要將動作直接放進View中即可。
    @IBAction func showMessage(sender: UIButton) {
        let alertController = UIAlertController(title: "Welcome to My First App", message: "Hello World", preferredStyle: UIAlertController.Style.alert)
        alertController.addAction(UIAlertAction(title: "OK", style: UIAlertAction.Style.default, handler: nil))
        present(alertController, animated: true, completion: nil)
    }

連結方式很"抽象",以外接滑鼠為例,回到Main畫面,點選button,按住右鍵就會拉出直線,將直線拖拉到(按鈕仍然維持在原本位置上)畫面上方有三個按鈕的最左邊,也就是viewcontroller上。放開右邊按鈕,就會跳出viewcontroller中可以連結的function。例如剛剛的showmessagexxxx。完成。
storyboard使用就是uikit,更多操作說明連結
對應這幾年推出更新的開發方案稱為swiftUI連結


MVC架構

基礎包括SWIFT的語法(連結

Basic Chat是MVC架構(藍芽的部分紀錄在另外一篇),無論是Android或是XCode都大量運用MVC,也算是軟體工程的一大進步吧。
MODEL沒有內容
VIEW很簡單
CONTROL有兩個
    ConsoleViewController 負責與VIEW溝通
    包含在ViewController中

MAIN中有三個項目,這讓我想到,如何在MAIN中增加VIEW(連結)
NAVIGATION CONTROLLER(找不到)
VIEW CONTROLLER
CONSOLE VIEW CONTROLLER

IDE編輯技巧

使用tab會跳出可選擇項目
滑鼠點擊某個文字後,按下option,就會跳出這個物件能夠使用的項目

執行:模擬器

menu->product->run 或是右邊箭頭,就會開始執行,執行有幾種,若有裝模擬器就能往模擬器送,模擬器是要另外下載IOS模擬器(模擬器是否支援藍牙不確定)。當設定過一次後,會記住。模擬器本身是個單獨的application,這個概念在Android Studio是一樣的。
更改設定的位置連結
模擬器不具備藍芽功能

執行:DEBUG

程式中加入print("hello"),會在xcode的右下方出現hello。  連結

print("Function: \(#function),Line: \(#line)")
結果是 Function: centralManager(_:didDiscover:advertisementData:rssi:),Line: 169
print("Peripheral Discovered: \(peripheral)")
結果是 Peripheral Discovered: <CBPeripheral: 0x28353e630, identifier = DDBFB78C-8690-C039-877E-556D31A8DA1B, name = OneTouch J05D, mtu = 0, state = disconnected>



執行:實機

參考 連結。成功。


SWIFT:語法



SWIFT:畫面進階

連結.  背景是深色會有錯誤
連結  動畫功能,因為工作需要顯示進度

BLE

理論:介紹(連結 連結 連結)。

基本character:範例(連結)。完整範例(連結 GITHUUB)。尋找和管理BLE裝置。方式有二,最直覺是右上方文字啟動,比較特別是程式啟動畫面切到viewcontroller,因為viewcontroller有繼承CBCentralManagerDelegate,只要進入這個頁面就會開始啟動,若先前已經允許藍芽,當藍芽是啟動狀況就會執行startScanning。

  1. 找到空間中全部藍芽裝置 centralManager?.scanForPeripherals(withServices: nil , options: [CBCentralManagerScanOptionAllowDuplicatesKey:true])
  2. 列印出各個項目(可能上百個,會進入的下面function)func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { }
    在這個function print("Peripheral Discovered: \(peripheral)"). 結果是 Peripheral Discovered: <CBPeripheral: 0x28353e630, identifier = DDBFB78C-8690-C039-877E-556D31A8DA1B, name = OneTouch J05D, mtu = 0, state = disconnected>
    有時候會重複,但沒有關係。RSSI : 訊號強弱  Advertisement : BLE 裝置透過 Advertising 告知周邊 BLE 裝置自己的存在,其中, 考慮到 WiFi 的干擾,Advertising 封包在以下 3 個 bluetooth channel 上廣播:channel 37 (2402 MHz), channel 38 (2426 MHz), 和 channel 39 (2480 MHz)
  3. 連線 centralManager.connect(peripheral, options: nil)  //參數很多,不用理會( 連結 )。連線後,有兩種反應,一種是成功,一種是失敗。
    centralManager(CBCentralManager, didConnect: CBPeripheral)
    centralManager(CBCentralManager, didFailToConnect: CBPeripheral, error: Error?)
    實驗結果是onetouch無法connect,下載了appstore軟體也沒有辦法連結,因此有點病急亂投醫,胡亂搞。但原相可以往下走,暫時歸因於硬體因素?
  4. Service。連結
    stopscan
    peripheral.delegate = self
    peripheral.discoverServices(nil)
    func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
    print(“Found \(services.count) services! :\(services)”)
    對每個services可以取得數字確認是否符合,並且繼續詢問後續characteristic,確認符合Service和Characteristic。另外一種做法是,scan的時候就直接填入service號碼,只有符合號碼才會顯示出來。
  5. Characteristic
    func peripheral(peripheral: CBPeripheral,didDiscoverCharacteristicsForService service: CBService,error: NSError?)
    peripheral.readValueForCharacteristic(characteristic)
    func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?)
    print(“characteristic uuid: \(characteristic.UUID), value: \(characteristic.value)”)
    if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Rx)  {
    rxCharacteristic = characteristic
    BlePeripheral.connectedRXChar = rxCharacteristic
    peripheral.setNotifyValue(true, for: rxCharacteristic!)
    peripheral.readValue(for: characteristic)
    print("RX Characteristic: \(rxCharacteristic.uuid)")
    }
    if characteristic.uuid.isEqual(CBUUIDs.BLE_Characteristic_uuid_Tx)
    {
    txCharacteristic = characteristic
    BlePeripheral.connectedTXChar = txCharacteristic
    print("TX Characteristic: \(txCharacteristic.uuid)")
    }
  6. Bonding,這步驟完成才算是pairing完成。裝置列表會在table中,點選其中一個就會connectToDevice。也就是後續寫入和讀取資料。
  7. 寫入資料
    peripheral.writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse)
    func peripheral(peripheral: CBPeripheral,didWriteValueForCharacteristic characteristic: CBCharacteristic,error: NSError?)
    print(“Succeeded!”)
    writeValueForCharacteristic的方法將值寫入characteristic
    CBCharacteristicWriteWithResponse   CBPeripheralDelegate didwriteValueFor
    CBCharacteristicWriteWithoutResponse    不能使用上面方法判斷
  8. 讀出資料
  9. 斷線didDisconnectPeripheral