2021年12月20日 星期一

(Simple) Chinese Hyphenation for Unity - 斷詞

本篇使用自然語言處理其中最基礎的一環,就是斷詞。斷詞方法有很多,這裡只舉長詞優先。長詞優先,主要中文特性的規範存在「字→詞→句」構成。需要由詞的部分開始下手。

所先需要資料庫存放詞語數據,再由演算法比對的方式來呈現。得到結果後就可以做出各式各樣的功能 (如: 關鍵字搜尋)。

GitHub 專案

 

 

 

 

 

 

 

 

 

 

 

 

 

Hyphenation 腳本(斷詞類別)

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

public abstract class Hyphenation
{
    protected List<string> ward;
    protected string dataBaseTitlle;

    public Hyphenation(List<string>ward, string dataBaseTitlle)
    {
        this.ward = ward;
        this.dataBaseTitlle = dataBaseTitlle;
    }

    public abstract List<string> reverse(MySQLFunction mySQLFunction);
    public abstract List<string> forward(MySQLFunction mySQLFunction);

    public abstract List<string> speech(MySQLFunction mySQLFunction);
}

HyphenationSetting 腳本

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

public class HyphenationSetting : Hyphenation
{
    private int forwardWardNumber = 0;
    private int reverceWardNumber = 0;

    public HyphenationSetting(List<string> ward, string dataBaseTitlle) : base(ward, dataBaseTitlle) { }

    // 正向
    public override List<string> forward(MySQLFunction mySQLFunction)
    {
        List<string> list = new List<string>();
        list.Clear();

        forwardWardNumber = 0;

        while (ward.Count >= 1)
        {
            if (forwardWardNumber < ward.Count)
            {
                if (ward[forwardWardNumber] != "")
                {
                    for (int y = 0; y <= ward[forwardWardNumber].Length; y++)
                    {
                        string ForwardMessage = ward[forwardWardNumber].Substring(0, ward[forwardWardNumber].Length - y);
                        if (ForwardMessage == mySQLFunction.inquire(dataBaseTitlle, 0, ForwardMessage))
                        {
                            list.Add(ForwardMessage);
                            ward[forwardWardNumber] = ward[forwardWardNumber].Remove(0, ForwardMessage.Length);
                        }
                        else if (ForwardMessage.Length == 1 && ward[forwardWardNumber] != mySQLFunction.inquire(dataBaseTitlle, 0, ForwardMessage))
                        {
                            list.Add(ForwardMessage);
                            ward[forwardWardNumber] = ward[forwardWardNumber].Remove(0, ForwardMessage.Length);
                        }
                    }
                }
                else
                    forwardWardNumber += 1;
            }
            else ward.Clear();
        }

        return list;
    }

    // 反向
    public override List<string> reverse(MySQLFunction mySQLFunction)
    {
        List<string> list = new List<string>();
        list.Clear();

        reverceWardNumber = 0;

        while (ward.Count >= 1)
        {
            if (reverceWardNumber < ward.Count)
            {
                if (ward[reverceWardNumber] != "")
                {
                    for (int y = 0; y <= ward[reverceWardNumber].Length; y++)
                    {
                        string ReverseMessage = ward[reverceWardNumber].Substring(y);

                        if (ReverseMessage == mySQLFunction.inquire(dataBaseTitlle, 0, ReverseMessage))
                        {
                            list.Add(ReverseMessage);
                            ward[reverceWardNumber] = ward[reverceWardNumber].Substring(0, ward[reverceWardNumber].Length - ReverseMessage.Length);
                        }
                        else if (ReverseMessage.Length <= 1 && ReverseMessage != mySQLFunction.inquire(dataBaseTitlle, 0, ReverseMessage))
                        {
                            list.Add(ReverseMessage);
                            ward[reverceWardNumber] = ward[reverceWardNumber].Substring(0, ward[reverceWardNumber].Length - ReverseMessage.Length);
                        }
                    }
                }
                else
                    reverceWardNumber += 1;
            }
            else ward.Clear();
        }

        return list;
    }

    // 詞性
    public override List<string> speech(MySQLFunction mySQLFunction)
    {
        List<string> list = new List<string>();

        foreach (string str in ward)
        {
            if (mySQLFunction.inquire(dataBaseTitlle, 1, str) != "")
                list.Add(mySQLFunction.inquire(dataBaseTitlle, 1, str));

            else list.Add("?");
        }

        return list;
    }
}

設計介面:

  • System - (Unity UI Text)
  • UserMessage - (Unity UI Text)
  • InputMessage - (Unity UI InputField)
  • Enter - (Unity UI Button)
  • Exit - (Unity UI Button)
  • Result - (Unity UI Text)
  • ResultMessage - (Unity UI Image)
    • Message - (Unity UI Text)
  • Horizontal - (Unity UI Scrollbar) 

以下3張圖片:

  • ResultMessage - (Unity UI Image) 組件設定
    • Message - (Unity UI Text) 組件設定
  • Horizontal - (Unity UI Scrollbar) 組件設定

image

image

image

2021年12月16日 星期四

Joystick Layout for Unity3D

常常看到手機遊戲都有Joystick 圖示來控制角色移動,按鈕控制角色: 跳躍,攻擊.....等等的功能,大概花時間研究了一下,可以用UnityUI的屬性方式來進行。

操作之前,我們可以理解成介面都是由圖片方式來進行與操作者互動。

GitHub 專案


例如:

  • 角色攻擊,玩家就會去點擊攻擊的指令,那個指令就可以當成是一個按鈕方式來進行觸發。
  • 按鈕圖示可以換成攻擊圖片與做出點擊按鈕震動動畫效果與玩家進行人機互動方式呈現。

Joystick 圖示

以上圖示Joystick 圖示按鈕

結果:












以下藉由Unity.EventSystems interface 方式來進行撰寫功能。

Joystick -- C# 腳本

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Joystick : MonoBehaviour, IDragHandler, IPointerUpHandler, IPointerDownHandler
{
    // Init
    protected Image container;
    protected Image joystick;
    protected Vector3 InputDirection = Vector3.zero;

    public void OnDrag(PointerEventData ped)
    {
        Vector2 position = Vector2.zero;

        // Get InputDirection
        RectTransformUtility.ScreenPointToLocalPointInRectangle(
            container.rectTransform,
            ped.position,
            ped.pressEventCamera,
            out position
        );

        float x = (position.x / container.rectTransform.sizeDelta.x);
        float y = (position.y / container.rectTransform.sizeDelta.y);

        InputDirection = new Vector3(x, y, 0);
        InputDirection = (InputDirection.magnitude > 1) ? InputDirection.normalized : InputDirection;

        // Define the area in which joystick can move around
        joystick.rectTransform.anchoredPosition = new Vector3(
            InputDirection.x * container.rectTransform.sizeDelta.x / 3,
            InputDirection.y * container.rectTransform.sizeDelta.y / 3
        );
    }

    public void OnPointerDown(PointerEventData ped)
    {
        OnDrag(ped);
    }

    public void OnPointerUp(PointerEventData ped)
    {
        InputDirection = Vector3.zero;
        joystick.rectTransform.anchoredPosition = Vector3.zero;
    }
}

InterfaceOBJ -- C# 腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;

public class InterfaceOBJ
{
    private Image imageObj;
    private Button buttonObj;
    private interfaceObj interfaceObj;

    public InterfaceOBJ(Image imag, interfaceObj interfaceObj)
    {
        this.imageObj = imag;
        this.interfaceObj = interfaceObj;
    }

    public InterfaceOBJ(Button button, interfaceObj interfaceObj)
    {
        this.buttonObj = button;
        this.interfaceObj = interfaceObj;
    }

    // image
    public void image(float pointX, float pointY, float sizeX, float sizeY)
    {
        interfaceObj.image(imageObj, pointX, pointY, sizeX, sizeY);
    }

    // button
    public void button(float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick)
    {
        interfaceObj.button(buttonObj, pointX, pointY, sizeX, sizeY, onClick);
    }
}

public interface interfaceObj
{
    void image(Image image, float pointX, float pointY, float sizeX, float sizeY);
    void button(Button button, float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick);
}

InterfaceObj -- C# 腳本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

public class InterfaceObj : interfaceObj
{
    public void button(Button button, float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick)
    {
        try
        {
            button.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
            button.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, sizeY);
            button.onClick.AddListener(onClick);
        }
        catch { }
    }

    public void image(Image image, float pointX, float pointY, float sizeX, float sizeY)
    {
        try
        {
            image.rectTransform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
            image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);
        }
        catch { }
    }
}

Layout_Main -- C# 腳本


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

public class Layout_Main : Joystick
{
    public Image fixedJoystick_image, handle_image;
    public Button jump_btn;

    InterfaceOBJ fixedJoystick, jump;

    public static Vector3 DIRCTION;
    public static bool JUMP_SW;

    // 計時器
    private float timeCount;
    private float timeCD = 1f;

    public static bool JUMP_ACTIVE;

    private void Start()
    {
        base.container = fixedJoystick_image;
        base.joystick = handle_image;

        fixedJoystick = new InterfaceOBJ(fixedJoystick_image, new InterfaceObj());
        fixedJoystick.image(0.23f, 0.4f, 0.2f, 0.35f);

        jump = new InterfaceOBJ(jump_btn, new InterfaceObj());
        jump.button(1.68f, 0.42f, 0.2f, 80, jump_onClkck);
    }

    private void Update()
    {
        DIRCTION = base.InputDirection;
        JUMP_ACTIVE = jumpCd();
    }

    void jump_onClkck()
    {
        if (JUMP_ACTIVE == true)
        {
            JUMP_SW = true;
            timeCount = timeCD;
        }
    }

    // 跳躍冷卻時間
    public bool jumpCd()
    {
        return ((timeCount -= Time.deltaTime) <= 0) ? true : false;
    }
}

Player -- C# 腳本


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

public class Player : MonoBehaviour
{
    Rigidbody rigidbody;

   
    private float gravity = 10.0f, maxVelocityChange = 50f, jumpHeight = 1f;

    public float speed;

    void Start()
    {       
        rigidbody = GetComponent();
        rigidbody.freezeRotation = true;
        rigidbody.useGravity = false;
    }

    private void FixedUpdate()
    {
        if(Layout_Main.DIRCTION.magnitude != 1)
        {
            Vector3 position = new Vector3(Layout_Main.DIRCTION.x * speed, 0,
                Layout_Main.DIRCTION.y * speed);

            position = transform.TransformDirection(position);

            Vector3 velocity = rigidbody.velocity;
            Vector3 velocityChange = (position - velocity);

            velocityChange.x = Mathf.Clamp(velocityChange.x, -maxVelocityChange, maxVelocityChange);
            velocityChange.z = Mathf.Clamp(velocityChange.z, -maxVelocityChange, maxVelocityChange);
            velocityChange.y = 0;
            rigidbody.AddForce(velocityChange, ForceMode.VelocityChange);

            if (Layout_Main.JUMP_SW)         
                rigidbody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);

            if (Layout_Main.JUMP_ACTIVE == false)
                Layout_Main.JUMP_SW = false;
        }

        rigidbody.AddForce(new Vector3(0, -gravity * rigidbody.mass, 0));
    }

    // Jump
    float CalculateJumpVerticalSpeed()
    {
        return Mathf.Sqrt(2 * jumpHeight * gravity);
    }
}

Unity 介面設計:

  • Canvas - Unity UI(一定要)
  • FixedJoystick - Unity UI (Image)
    • Handle - Unity UI (Image) - 當FixedJoystick子物件
      • Handle 設定Width: 50, Height: 50
  • Jump_Btn - Unity UI (Image)
  • EventSystem - Unity UI (一定要)
  • Player - 3D物件(本文使用Unity內建物件)
  • Plane - 3D物件(本文使用內建物件)

image

Canvas 物件: 

  • 插入Layout_Main腳本

螢幕擷取畫面 2021-05-19 045114

Player 物件:

  • 插入Player腳本

image

2021年12月12日 星期日

GitHub 教學

所先需要幾個步驟:

  1. 註冊帳號
  2. 下載及安裝 Git fo Window
  3. 配置 Git
  4. 連接 GitHub
  5. 創建本地倉庫
  6. 上傳

1. 註冊帳號

2. 下載並安裝 Git for Window

3. 配置 Git

  • 打開 Git Bash

未命名       

  image

  • 建立SSH key 輸入指令: 
    • $ ssh-keygen -t rsa -C "your_email@youremail.com"
    • 再按Enter
  • 成功畫面:
  • image
  • 自動建立路徑 : 本文路徑
  • image

4. 連接 GitHub

  • 登入 GitHub 官網 → 使用者 → Setting
  • 未命名
  • 點(New SSH Keys) 綠色按鈕,並把 id_rsa.pub 檔案內容貼到以下面畫面,再打上Title 名稱。
  • 未命名
  • 成功畫面
  • image

 

5. 創建本地倉庫上傳

  • 再回到Git Bash 打上兩個指令
  • $git config --global user.name "Your Name"  
    • 檢查 $git config --global user.name
  • $git config --global user.email "email@example.com"
    • 檢查 $git config --global user.email
  • image
  • 再到 GitHub 點New repository
  • 未命名
  • 未命名
  • 再到命令提示字元,打下指令:
  • cd /d D:/GitHub/Code
    • cd /d 路徑名稱 (GitHub 存儲庫存放位置)
  • git clone git@github.com:gsp40213/PuchCard.git
    • git clone (GutHub 存儲庫 SSH 位置)
    • image
  • 再按下Enter後再輸入yes,再按Enter,路徑就可以看到建立GitHub 存儲庫資料,在命令提示字元輸入: dir
  • image
  • image

6. 上傳

  • 再把相關檔案丟到GitHub 存儲庫位置
  • image
  • 再到命令提示字元打上: git status
    • ​​​​​​路徑(GitHub存儲庫本機位置)一定要正確,否則會讀不到)
  • image
  • 再打上命令提示字元: git add -a 
  • image
  • 再輸入 git commit  -m "自行定義"
  • image
  • 再輸入: git push
  • image
  • 檢查官方是否上傳成功:
  • image

2021年12月11日 星期六

Unity 建立班表

又嘗試用Unity 做其他事情,最近看到班表這個有趣的事情,之前有貼過固定班格式與如何讀取日期的文章。

想要挑戰一下,完美的功能,如: 有日期、公司、選擇班別,班表內容是否超過當日的營業時間與休假跟加班計算....等功能。

本人比較懶,因此很少調整Unity 設計畫面,大致上都以程式碼部分直接調整,以下所使用的方式由Interface方式來呈現。

GitHub 相關位置

-----以下成功畫面-----

 

 

 

 

 

 

 

 

 

 

 

 

------------接下來就是 程式碼部份了------------

ExcelClass 腳本 (C#) :   

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

public abstract class ExcelClass
{
    public abstract class ClassInterface
    { 
        public abstract class Preset
        {
            public abstract void classFixed(int year, int month, string companyName, string unit, int staffNumber);
            public abstract void excelSave(int staffNumber);
        }
        
        public abstract class Formula
        {
            public abstract void createClass(int year, int month, string companyName, string unit, int staffNumber, int operAtingHours,
                bool dayShift, bool night, bool bigNight);
            public abstract void excelSave(int satffNumber);
        }
    }
}

PresetClass 腳本

using System.IO;
using OfficeOpenXml;
using System;
using System.Collections.Generic;

public class PresetClass : ExcelClass.ClassInterface.Preset
{
    // 建立資料位置
    private string folderPath = @"D:\班表\";
    private string filePath;

    // 檔案類別
    FileInfo fileInfo;
    Calendar.GetCalender getCalender = new GetCalender();

    // excel 組件
    public static ExcelPackage EXCEL_PACKAGE;
    public static ExcelWorksheet WORKSHEET;

    // Excel 固定格式 (年、職位、天、資料寫入縱)
    int companyNameYear = 1;                                        
    int positionNumber = 2;                                        
    int dayExcelNuber = 3;                                           
    int dataExcelNum = 4;

    public static List<Data_date> GET_Data = new List<Data_date>();

    public override void classFixed(int year, int month, string companyName, string unit, int staffNumber)
    {
        GET_Data.Clear();
        GET_Data = getCalender.calendarData(year, month, 1);

        if (!Directory.Exists(folderPath + @"\" + unit))
            Directory.CreateDirectory(folderPath + @"\" + unit);

        // 判斷檔案是否存在
        if (fileExist(unit, year, month))
        {
            fileInfo.Delete();
            fileInfo = new FileInfo(filePath);
        }


        EXCEL_PACKAGE = new ExcelPackage(fileInfo);
        WORKSHEET = EXCEL_PACKAGE.Workbook.Worksheets.Add(getCalender.calendarData(year, month, 1)[0].month + "月");

        // 寫入公司名稱
        WORKSHEET.Cells[companyNameYear, 1].Value = GET_Data[0].year + "年" + GET_Data[0].month + "月 " + companyName + " (" + "單位: " + unit + ")";
        WORKSHEET.Cells[companyNameYear, 1, 1, GET_Data.Count + 3].Merge = true;

        // 寫入部分(單位)
        WORKSHEET.Cells[positionNumber, 1].Value = unit;
        WORKSHEET.Cells[positionNumber, 1, positionNumber, GET_Data.Count + 3].Merge = true;
        // 表格上色
        TABLE_COLOR(positionNumber, 1, System.Drawing.Color.Yellow);

        foreach (var dayweekData in GET_Data)
        {
            WORKSHEET.Cells[dayExcelNuber, 1].Value = "員工";
            // 天與週次
            WORKSHEET.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 1].Value = dayweekData.week + dayweekData.day;

            // 休假
            WORKSHEET.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 2].Value = "休假";
            // 表格上色
            TABLE_COLOR(dayExcelNuber, GET_Data.Count + 2, System.Drawing.Color.Red);

            //加班
            WORKSHEET.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 3].Value = "加班";

            // 輸入員工姓名
            for (int x = 0; x < staffNumber; x++)
                WORKSHEET.Cells[dataExcelNum + x, 1].Value = "輸入姓名";

            // 自動調整距離
            WORKSHEET.Cells[WORKSHEET.Dimension.Address].AutoFitColumns();
        }
    }

    // excel save
    public override void excelSave(int staffNumber)
    {
        EXCEL_STYLE(1, 1, staffNumber + 3, GET_Data.Count + 3);
        EXCEL_PACKAGE.Save();
    }

    // 判斷檔案
    bool fileExist(string unit, int year, int month)
    {
        filePath = folderPath + @"\" + unit + @"\" + year.ToString() + "年" + month.ToString() + "月" + ".xlsx";
        fileInfo = new FileInfo(filePath);

        bool fileExist = fileInfo.Exists;

        return fileExist;
    }

    // 表格顏色
    public static void TABLE_COLOR(int fromRow, int fromCol, System.Drawing.Color color)
    {
        WORKSHEET.Cells[fromRow, fromCol].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
        WORKSHEET.Cells[fromRow, fromCol].Style.Fill.BackgroundColor.SetColor(color);
    }

    public static void EXCEL_STYLE(int fromRow, int fromCol, int toRow, int toCol)
    {
        // 字形
        WORKSHEET.Cells.Style.Font.Name = "標楷體";
        // 文字大小
        WORKSHEET.Cells.Style.Font.Size = 14;
        // 水平置中
        WORKSHEET.Cells.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
        // 垂直中
        WORKSHEET.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
        // 表格框線
        WORKSHEET.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
        WORKSHEET.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
        WORKSHEET.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
        WORKSHEET.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Medium;
    }
}

FormulaClass 腳本

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using OfficeOpenXml;

public class FormulaClass : ExcelClass.ClassInterface.Formula
{
    // 檔案類別
    FileInfo fileInfo;

    // Excel 固定格式 (資料寫入縱)
    int dataExcelNum = 4;

    ExcelClass.ClassInterface.Preset presetClass = new PresetClass();

    public override void createClass(int year, int month, string companyName, string unit, int staffNumber, int operAtingHours,
        bool dayShift, bool night, bool bigNight)
    {
        presetClass.classFixed(year, month, companyName, unit, staffNumber);

        int checkExcelNum = dataExcelNum + staffNumber;

        int classStateNum = 0;

        string className1 = "D";
        string className2 = "E";
        string className3 = "N";

        int dayShiftAdd = 0;
        int nightAdd = 0;
        int bigNightAdd = 0;

        // 營業時數
        PresetClass.WORKSHEET.Cells[checkExcelNum + 1, 1].Value = "營業時間 ( " + operAtingHours + "小時 )";
        PresetClass.TABLE_COLOR(checkExcelNum + 1, 1, System.Drawing.Color.Red);
        PresetClass.WORKSHEET.Cells[checkExcelNum + 1, 1].AutoFitColumns(50);

        // 狀態1: 3班都選擇(三班制)
        if (dayShift == true && night == true && bigNight == true)
        {
            // 白班
            for (int x = 2; x <= 6; x++)
            {
                classState(checkExcelNum, x, toggleMessage(dayShift, className1 + classTable(dayShiftAdd)), dayShiftAdd);
                dayShiftAdd += 1;
            }

            // 小夜班(晚班)
            for (int x = 7; x <= 11; x++)
            {
                classState(checkExcelNum, x, toggleMessage(night, className2 + classTable(nightAdd)), nightAdd);
                nightAdd += 1;
            }

            // 大夜班(夜班)
            for (int x = 12; x <= 16; x++)
            {
                classState(checkExcelNum, x, toggleMessage(bigNight, className3 + classTable(bigNightAdd)), bigNightAdd);
                bigNightAdd += 1;
            }

            classStateNum = 1;
        }

        // 狀態2: 2班都選擇 - 白班,晚班(二班制)
        if (dayShift == true && bigNight == true && night != true)
        {
            // 白班
            for (int x = 2; x <= 6; x++)
            {
                classState(checkExcelNum, x, toggleMessage(dayShift, className1 + classTable(dayShiftAdd)), dayShiftAdd);
                dayShiftAdd += 1;
            }

            // 大夜班(夜班)
            for (int x = 7; x <= 11; x++)
            {
                classState(checkExcelNum, x, toggleMessage(bigNight, className3 + classTable(bigNightAdd)), bigNightAdd);
                bigNightAdd += 1;
            }

            classStateNum = 2;
        }

        if (dayShift == true && night != true && bigNight != true)
        {
            // 白班
            for (int x = 2; x <= 6; x++)
            {
                classState(checkExcelNum, x, toggleMessage(dayShift, className1 + classTable(dayShiftAdd)), dayShiftAdd);
                dayShiftAdd += 1;
            }

            classStateNum = 3;
        }

        // 加班公式
        overtimeFormula(checkExcelNum, classStateNum, staffNumber, operAtingHours);
    }

    public override void excelSave(int satffNumber)
    {
        PresetClass.EXCEL_STYLE(1, 1, satffNumber + 3, PresetClass.GET_Data.Count + 3);
        PresetClass.EXCEL_PACKAGE.Save();
    }

    // 加班公式
    void overtimeFormula(int checkExcelNum, int classStateNum, int staffNumber, int operAtingHours)
    {
        // 橫向
        for (int x = 0; x < staffNumber; x++)
        {
            // 加班
            PresetClass.WORKSHEET.Cells[dataExcelNum + x, PresetClass.GET_Data.Count + 3].Formula = formulaHorizontal(1, dataExcelNum + x, 2);
            PresetClass.WORKSHEET.Cells[dataExcelNum + x, PresetClass.GET_Data.Count + 2].Formula = formulaHorizontal(2, dataExcelNum + x, 2);
        }

        for (int x = 0; x < PresetClass.GET_Data.Count; x++)
        {
            // 3班
            if (classStateNum == 1)
            {
                // 檢查營業時間
                PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2].Formula = formula_vertical_openBusiness(checkExcelNum, x + 2, classStateNum);
                var cont = PresetClass.WORKSHEET.ConditionalFormatting.AddGreaterThan(PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2]);
                cont.Style.Font.Color.Color = System.Drawing.Color.Red;
                cont.Formula = operAtingHours.ToString();

                int dayShiftTable = 0;
                int nightTable = 0;
                int bigNightTable = 0;

                // D班含加班
                for (int i = 2; i <= 6; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"D"
                        + classTable(dayShiftTable) + "\"", "\"D" + classTable(dayShiftTable) + "\"", staffNumber);

                    dayShiftTable += 1;
                }

                // E班含加班
                for (int i = 7; i <= 11; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"E"
                        + classTable(nightTable) + "\"", "\"E" + classTable(nightTable) + "\"", staffNumber);

                    nightTable += 1;
                }

                // N班含加班
                for (int i = 12; i <= 16; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"N"
                        + classTable(bigNightTable) + "\"", "\"N" + classTable(bigNightTable) + "\"", staffNumber);

                    bigNightTable += 1;
                }

                // 畫線
                PresetClass.EXCEL_STYLE(checkExcelNum + 1, 1, checkExcelNum + 16, PresetClass.GET_Data.Count + 1);
            }

            // 2班
            if (classStateNum == 2)
            {
                // 檢查營業時間
                PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2].Formula = formula_vertical_openBusiness(checkExcelNum, x + 2, classStateNum);
                var cont = PresetClass.WORKSHEET.ConditionalFormatting.AddGreaterThan(PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2]);
                cont.Style.Font.Color.Color = System.Drawing.Color.Red;
                cont.Formula = operAtingHours.ToString();

                int dayShiftTable = 0;
                int bigNightTable = 0;

                // D班含加班
                for (int i = 2; i <= 6; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"D"
                        + classTable(dayShiftTable) + "\"", "\"D" + classTable(dayShiftTable) + "\"", staffNumber);

                    dayShiftTable += 1;
                }

                // N班含加班
                for (int i = 7; i <= 11; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"N"
                        + classTable(bigNightTable) + "\"", "\"N" + classTable(bigNightTable) + "\"", staffNumber);

                    bigNightTable += 1;
                }

                // 畫線
                PresetClass.EXCEL_STYLE(checkExcelNum + 1, 1, checkExcelNum + 11, PresetClass.GET_Data.Count + 1);
            }

            if (classStateNum == 3)
            {
                // 檢查營業時間
                PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2].Formula = formula_vertical_openBusiness(checkExcelNum, x + 2, classStateNum);
                var cont = PresetClass.WORKSHEET.ConditionalFormatting.AddGreaterThan(PresetClass.WORKSHEET.Cells[checkExcelNum + 1, x + 2]);
                cont.Style.Font.Color.Color = System.Drawing.Color.Red;
                cont.Formula = operAtingHours.ToString();

                int dayShiftTable = 0;

                // D班含加班
                for (int i = 2; i <= 6; i++)
                {
                    PresetClass.WORKSHEET.Cells[checkExcelNum + i, x + 2].Formula = formulaVerticalClassName(dataExcelNum, x + 2, "\"D"
                        + classTable(dayShiftTable) + "\"", "\"D" + classTable(dayShiftTable) + "\"", staffNumber);

                    dayShiftTable += 1;
                }

                // 畫線
                PresetClass.EXCEL_STYLE(checkExcelNum + 1, 1, checkExcelNum + 6, PresetClass.GET_Data.Count + 1);
            }
        }
    }

    // 公式 Excel 縱向(班別名稱)
    string formula_vertical_openBusiness(int rol, int col, int classState)
    {
        string result = "";

        string dayShiftResult = "";
        string nightResult = "";
        string bigNightResult = "";

        int dayShiftNum = 8;
        int nightNum = 8;
        int bigNightNum = 8;

        int dayShiftNum1 = 12;
        int bigNightNum1 = 12;

        // 3班制
        if (classState == 1)
        {
            // 白班
            for (int x = 2; x <= 6; x++)
            {
                dayShiftResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0, " + dayShiftNum + ",0) +";
                dayShiftNum += 1;
            }

            // 小夜(晚班)
            for (int x = 7; x <= 11; x++)
            {
                nightResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0, " + nightNum + ",0) +";
                nightNum += 1;
            }

            // 大夜(夜班)
            for (int x = 12; x <= 16; x++)
            {
                bigNightResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0," + bigNightNum + " ,0) +";
                bigNightNum += 1;
            }

            result = dayShiftResult + nightResult + bigNightResult;
        }

        // 兩班制
        if (classState == 2)
        {
            // 白班
            for (int x = 2; x <= 6; x++)
            {
                dayShiftResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0," + dayShiftNum1 + " ,0) +";
                dayShiftNum1 += 1;
            }

            // 大夜(夜班)
            for (int x = 7; x <= 11; x++)
            {
                bigNightResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0," + bigNightNum1 + " ,0) +";
                bigNightNum1 += 1;
            }

            result = dayShiftResult + bigNightResult;
        }

        // 一班制
        if (classState == 3)
        {

            // 白斑
            for (int x = 2; x <= 6; x++)
            {
                dayShiftResult += "IF(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "<> 0," + dayShiftNum + ",0) +";
                dayShiftNum += 1;
            }

            result = dayShiftResult;

        }

        result = result.Remove(result.LastIndexOf("+"), 1);

        return result;
    }

    // 公式: Excel 縱向(班別名稱)
    string formulaVerticalClassName(int rol, int col, string className, string className2, int staffNumber)
    {
        string result = "";

        for (int x = 0; x < staffNumber; x++)
        {
            string str = "IF(OR(" + PresetClass.WORKSHEET.Cells[rol + x, col] + "=" + className + ", +"
                + PresetClass.WORKSHEET.Cells[rol + x, col] + "=" + className2 + "), 1, 0) + ";
            result += str;
        }

        result = result.Remove(result.LastIndexOf("+"), 1);

        return result;
    }

    // 公式: Excel 橫向
    string formulaHorizontal(int state, int rol, int col)
    {
        string result = "";

        // 加班狀態 
        for (int x = 0; x < PresetClass.GET_Data.Count; x++)
        {
            if (state == 1)
            {
                string str = "IF(OR(" + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"D1\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"E1\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"N1\"), 1) + IF(OR(" + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"D2\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"E2\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"N2\"), 2) + IF(OR("
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"D3\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"E3\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"N3\"), 3) + IF(OR(" + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"D4\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"E4\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "= \"N4\"), 4) +";

                result += str;
            }

            // 假別
            if (state == 2)
            {
                string str = "IF(OR(" + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"休\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"特\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"病\", " + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"公\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"喪\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"婚\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"公病\"," + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"事\","
                    + PresetClass.WORKSHEET.Cells[rol, col + x] + "=\"災\",),1)+";

                result += str;
            }
        }

        result = result.Remove(result.LastIndexOf("+"), 1);

        return result;
    }

    // 班別區分顏色
    void classState(int checkExcelNum, int frequency, string message, int addClassTable)
    {
        PresetClass.WORKSHEET.Cells[checkExcelNum + frequency, 1].Value = message;

        if (addClassTable.Equals(0))
            PresetClass.TABLE_COLOR(checkExcelNum + frequency, 1, System.Drawing.Color.Orange);
        else
            PresetClass.TABLE_COLOR(checkExcelNum + frequency, 1, System.Drawing.Color.Yellow);
    }

    // 加班訊息表示
    string classTable(int table)
    {
        return (table.Equals(0)) ? "" : table.ToString();
    }

    // toggle 布林為訊息
    string toggleMessage(bool toggleBool, string message)
    {
        return (toggleBool == true) ? message : "";
    }
}

2021年12月8日 星期三

C# 抓取指定月份顯示民國 和 Day與Week

 利用 C# 抓取年月與週,以下程式設計方式: Interface方式來呈現

Calendar (C#) 腳本----參數管理----:  

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

public class Calendar 
{
    private string year;    // 年
    private string month;   // 月
    private string days;    // 日

    GetCalenderData getCalenderData;

    public Calendar(string year, string month, string day, GetCalenderData getCalenderData)
    {
        this.year = year;
        this.month = month;
        this.days = day;
        this.getCalenderData = getCalenderData;
    }

    public List<Data_data> getData()
    {
        return getCalenderData.getData(int.Parse(year), int.Parse(month), int.Parse(days));
    }

    public int dayNumber()
    {
        return getCalenderData.dayNumber(int.Parse(year), int.Parse(month), int.Parse(days));
    }
}

public interface GetCalenderData
{
    List<Data_data> getData(int year, int month, int day);     // 取得行事曆資料
    int dayNumber(int year, int month, int day);
}

// 暫存用
public class Data_data
{
    public string year;
    public string month;
    public string day;
    public string week;

    public Data_data(string year, string month, string day, string week)
    {
        this.year = year;
        this.month = month;
        this.day = day;
        this.week = week;
    }
}
InterfaceCalender (C#) 腳本----方法撰寫---- :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;

public class InterfaceCalender : GetCalenderData
{
    DateTime dateTime;

    public int dayNumber(int year, int month, int day)
    {
        int dayNum = 0;

        for (int x = 1; x <= DateTime.DaysInMonth(dateTime.Year, dateTime.Month); x++)
        {
            dayNum = x;
        }
    
        return dayNum;
    }

    // 取得行事曆資料
    public List<Data_data> getData(int year, int month, int day)
    {
        List<Data_data> classExcels = new List<Data_data>();

        for(int i = 1; i <= DateTime.DaysInMonth(dateTime.Year, dateTime.Month); i++)
        {
            dateTime = new DateTime(year, month, i);
            
            classExcels.Add(new Data_data(yearConversion(dateTime.Year).ToString(), dateTime.Month.ToString(), i.ToString(),
                weekEngToChin(dateTime.DayOfWeek.ToString())));
    }

        return classExcels;
    }

    // 西元轉民國(公式)
    int yearConversion(int inVid)
    {
        return inVid - 1911;
    }

    // 英文轉中文(星期)
    string weekEngToChin(string dayOfWeek)
    {
        string chinWeek = "";

        if (dayOfWeek.ToString().Equals("Monday"))
            chinWeek = "一";
        if (dayOfWeek.ToString().Equals("Tuesday"))
            chinWeek = "二";
        if (dayOfWeek.ToString().Equals("Wednesday"))
            chinWeek = "三";
        if (dayOfWeek.ToString().Equals("Thursday"))
            chinWeek = "四";
        if (dayOfWeek.ToString().Equals("Friday"))
            chinWeek = "五";
        if (dayOfWeek.ToString().Equals("Saturday"))
            chinWeek = "六";
        if (dayOfWeek.ToString().Equals("Sunday"))
            chinWeek = "日";

        return chinWeek;
    }
}
TestRun (C#) 腳本----執行----:

public class TestRun : MonoBehaviour{ Calendar calendar; void Start() { calendar = new Calendar("2021", "12", "1", new InterfaceCalender()); } void Update() { foreach(var str in calendar.getData()) { Debug.Log(str.month +"月" + str.day + "日" + "星期:" + str.week); } } }

結果圖:


2021年9月30日 星期四

Unity UI 基本跑馬燈

 文字跑馬燈,所先要了解,怎麼顯示模式。

大致上作法 可以用兩種方式來使用。

  • 時間方式計算
  • 數字累加

本文採取第二種數字累加的方式來呈現。

邏輯:   數字: 1 代表1個字,表示說 數字累加的方式來顯示文字數量。

-------------------------------------------

本文都採取使用C# 方式來進行編排,不太用到Unity設計界面來操作設定,

但是要先建立需要使用的遊戲物件即可。此篇介面採取比例 (16:9)

使用的遊戲物件:

  • Canvas (Unity UI)
  • Text (Unity UI)
  • EventSystem (Unity UI)
  • Camera
完成結果後

image























-----------------------------------

程式碼部分:   

腳本名稱: InterfaceObj

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

// 介面
public class InterfaceObj
{
    // image Obj 
    public Image imageObj(Image image, Color color , float pointX, float pointY, float sizeX, float sizeY)
    {
        image.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
        image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);

        image.color = color;

        return image;
    }

    // text Obj
    public Text textObj(Text text, string message, FontStyle fontStyle, Color color ,int textSize, float pointX, float pointY, float sizeX, float sizeY)
    {
        text.text = message;
        text.fontStyle = fontStyle;
        text.color = color;
        text.fontSize = textSize;

        text.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
        text.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);

        return text;
    }
}

// 介面效果類別
public class interfaceAfterEffects
{
    /*--------------------------
        * 文字效果
    --------------------------*/

    private float marquee_startTime = 0;  // 跑馬燈開始時間

    // 文字跑馬燈
    public void textEffects(TextEffects effects, Text text, string message, float speed, bool start)
    {
     text.text = text_Marquee(message, speed, start);   
    }

    // 跑馬燈
    private string text_Marquee(string message, float speed, bool start)
    {
        return message.Substring(0, (int)text_marquee_timeData(message.Length, speed, start));
    }

    // 計數器(跑馬燈顯示)
    private float text_marquee_timeData(float textSize, float speed, bool start)
    {
        float time = (marquee_startTime < textSize && start.Equals(true)) ? marquee_startTime += speed :
            (start.Equals(false)) ? marquee_startTime = 0 : marquee_startTime = textSize;

        return time;
    }
}

腳本名稱: UI_Layout

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class UI_Layout : MonoBehaviour
{
    InterfaceObj interfaceObj = new InterfaceObj();

    // 文字訊息(系統)
    public void system_mesage_text(Text cameraModel_Text, Text recording_Text, Text InternalLab_Text, Text section8_Text, Text scanning_Text, Text activated, float pointX, float pointY, float sizeX, float sizeY)
    {
        interfaceObj.textObj(cameraModel_Text, "CAMERA 05s", FontStyle.Normal, new Color(0, 0.9f, 1, 1), (Screen.width / 2) / 10, 0.43f, 1.7f, 0.66f, 0.21f);
        interfaceObj.textObj(recording_Text, "REC.", FontStyle.Normal, new Color(1, 1, 1, 1), (Screen.width / 2) / 16, 0.19f, 1.4f, 0.15f, 0.13f);
        interfaceObj.textObj(InternalLab_Text, "INTERNAL LAB 13", FontStyle.Normal, new Color(1, 1, 1, 1), (Screen.width / 2) / 27, 0.55f, 1.44f, 0.32f, 0.1f);
        interfaceObj.textObj(section8_Text, "SECTION 8 - LEVEL 06", FontStyle.Normal, new Color(1, 1, 1, 1), (Screen.width / 2) / 29, 0.58f, 1.33f, 0.38f, 0.08f);
        interfaceObj.textObj(scanning_Text, "SCANNING", FontStyle.Normal, new Color(1, 1, 1, 1), (Screen.width / 2) / 12, 0.34f, 0.85f, 0.47f, 0.18f);
        interfaceObj.textObj(activated, "SYSTEM ACTIVATED", FontStyle.Normal, new Color(1, 1, 1, 1), (Screen.width / 2) / 18, 0.4f, 0.7f, 0.6f, 0.12f);
    }
}

腳本名稱: Layout_Run

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

public class Layout_Run : UI_Layout
{
    public Text cameraModel_Text;
    public Text recording_Text;
    public Text internalLab_Text;
    public Text section8_Text;
    public Text scanning_Text;
    public Text activated_Text;

    // 跑馬燈
    interfaceAfterEffects scanning_Text_marquess = new interfaceAfterEffects();
    interfaceAfterEffects activated_Text_marquess = new interfaceAfterEffects();

    public bool sw = false;

    private void Update()
    {
        systemLayoutMessge();

        if (Input.GetKeyDown(KeyCode.W))
            sw = !sw;
    }

    private void systemLayoutMessge()
    {
   
        system_mesage_text(cameraModel_Text, recording_Text, internalLab_Text, section8_Text, scanning_Text, activated_Text, pointX, pointY, sizeX, sizeY);

        // 文字跑馬燈
        scanning_Text_marquess.textEffects(scanning_Text, "SCANNING", 0.6f, sw);
        activated_Text_marquess.textEffects(activated_Text, "SYSTEM ACTIVATED", 0.4f, sw);

    }
}

2021年7月29日 星期四

Visual Studio Code for Unity ( Visual Studio Code 撰寫Unity 程式)

目前 很夯 Visual Studio Code  來撰寫程式,主要是開啟速度較快與程式撰寫者,可自行匯入模組,那我們如何進行用 Visual Studio Code 來撰寫Unity底下程式,如步驟以下:

官方連結:  Visual Studio Code  

下載完成後_介面如下:












Unity開發,這裡使用 C#語言來撰寫,因此下載 .NET Core SDK 工具來協助方便撰寫。

官方連結:  .NET Core SDK 

再到此圖紅色框框點選下載



下載安裝後,在安裝常用組件:






再到Unity3D 軟體,設定程式腳本編譯器選擇



























出現以下圖片結果表示成功了 XD,若沒辦法顯示,請進行重新開機即可






2021年6月29日 星期二

Unity to Excel 建立班表 (固定格式)

因由Unity 發佈後,無法建立Excle原因,主要是Dll少檔案

Excel 全部相關DLL下載

提取码:0xso

備用載點

---------------------- Excel 班表格式 ------------------------------

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Data;
using Excel;
using OfficeOpenXml;
using System;

public class CreateRoster_Excel
{
    private int _year, _month;
    private string _companyName, _unit;
   
    public CreateRoster_Excel(int year, int month, string companyName, string unit)
    {
        this._year = year;
        this._month = month;
        this._companyName = companyName;
        this._unit = unit;
    }

    // 建立資料位置
    private string folderPath = @"D:\班表\";
    // 檔案名稱
    private string fileName = "班表";
    // 檔案路徑
    private string filePath;                                             

    // Excel 固定格式
    int companyNameYear = 1;                                      // 年
    int positionNumber = 2;                                       // 職位
    int dayExcelNuber = 3;                                        // 天

    // excel 組件
    ExcelPackage excelPackage;
    ExcelWorksheet workSheets;

    // 每年每月類別
    QueryMonthAndDays queryMonthAndDays;

    // 檔案類別
    FileInfo fileInfo;

    public void test()
    {
        createExcelFile();
        excel_Fixed();
    }

    // excel 固定格式建立
    private void excel_Fixed()
    {
        queryMonthAndDays = new QueryMonthAndDays(_year, _month, 1);

        excelPackage = new ExcelPackage(fileInfo);
        workSheets = excelPackage.Workbook.Worksheets.Add(queryMonthAndDays.getData()[0].month + "月");

        // 寫入公司名稱
        workSheets.Cells[companyNameYear, 1].Value = queryMonthAndDays.getData()[0].year + "年" + queryMonthAndDays.getData()[0].month + "月 " + _companyName + " (" + "單位: " + _unit + ")";
        workSheets.Cells[companyNameYear, 1, 1, queryMonthAndDays.getData().Count + 3].Merge = true;

        // 寫入單位
        workSheets.Cells[positionNumber, 1].Value = _unit;
        workSheets.Cells[positionNumber, 1, positionNumber, queryMonthAndDays.getData().Count + 3].Merge = true;
        // 表格上色
        tableColor(positionNumber, 1, System.Drawing.Color.Yellow);

        // 寫入年月與公司名稱
        foreach (var dayweekData in queryMonthAndDays.getData())
        {
            workSheets.Cells[dayExcelNuber, 1].Value = "員工";
            // 天與週次
            workSheets.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 1].Value = dayweekData.week + dayweekData.day;

            // 休假
            workSheets.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 2].Value = "休假";
            // 表格上色
            tableColor(dayExcelNuber, queryMonthAndDays.getData().Count + 2, System.Drawing.Color.Red);

            //加班
            workSheets.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 3].Value = "加班";
        }

        excelStyle(1, 1, 3);
        excelPackage.Save();
    }

    // excel 樣式
    void excelStyle(int fromRow, int fromCol, int toRow)
    {
        // 字形
        workSheets.Cells.Style.Font.Name = "標楷體";
        // 文字大小
        workSheets.Cells.Style.Font.Size = 16;
        // 水平置中
        workSheets.Cells.Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center;
        // 垂直中
        workSheets.Cells.Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center;
        // 表格框線
        workSheets.Cells[fromRow, fromCol, toRow, queryMonthAndDays.getData().Count + 3].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
        workSheets.Cells[fromRow, fromCol, toRow, queryMonthAndDays.getData().Count + 3].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
        workSheets.Cells[fromRow, fromCol, toRow, queryMonthAndDays.getData().Count + 3].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
        workSheets.Cells[fromRow, fromCol, toRow, queryMonthAndDays.getData().Count + 3].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
    }

    // 表格顏色
    void tableColor(int fromRow, int fromCol, System.Drawing.Color color)
    {
        workSheets.Cells[fromRow, fromCol].Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
        workSheets.Cells[fromRow, fromCol].Style.Fill.BackgroundColor.SetColor(color);
    }

    // 建立檔案
    private void createExcelFile()
    {
        // 建立資料夾
        if (!Directory.Exists(folderPath + @"\" + _unit))
            Directory.CreateDirectory(folderPath + @"\" + _unit);

        // 判斷檔案是否存在
        if (fileExist())
        {
            fileInfo.Delete();
            fileInfo = new FileInfo(filePath);
        }

    }

    // 檔案是否存在
    bool fileExist()
    {
        filePath = folderPath + @"\" + _unit + @"\" + _year.ToString() + "年" + _month.ToString() + "月" + ".xlsx";
        fileInfo = new FileInfo(filePath);

        bool fileExist = fileInfo.Exists;

        return fileExist;
    }
 }

---------------------------以下每年每月時間抓取---------------------------------

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


// List 管理
public class Data_data
{
    public string year { get; set; }        // 年
    public string month { get; set; }       // 月
    public string day { get; set; }         // 日
    public string week { get; set; }        // 週期

    public Data_data(string year, string month, string day, string week)
    {
        this.year = year;
        this.month = month;
        this.day = day;
        this.week = week;
    }
}

public class QueryMonthAndDays
{
    int _year;      // 年
    int _month;     // 月
    int _day;       // 日

    DateTime startdate;

    // 建構子
    public QueryMonthAndDays(int year, int month, int day)
    {
        this._year = year;
        this._month = month;
        this._day = day;

        startdate = new DateTime(_year, _month, _day);
    }

    // 天數
    public int DayNumber()
    {
        int dayNumber = 0;
        for(int x=1; x <= DateTime.DaysInMonth(startdate.Year, startdate.Month); x++)
        {
            dayNumber = x;
        }

        return dayNumber;
    }

    // 執行
    public List<Data_data> getData()
    {
        List<Data_data> data = new List<Data_data>();
        
        for (int x = 1; x <= DateTime.DaysInMonth(startdate.Year, startdate.Month); x++)
        {
            startdate = new DateTime(startdate.Year, startdate.Month, x);

            data.Add(new Data_data(vidToRepublic(startdate.Year).ToString(), startdate.Month.ToString(), x.ToString(),
                weekEngToChin(startdate.DayOfWeek.ToString())));      
        }

        return data;
    } 

    // 西元轉換民國 (公式)
    int vidToRepublic(int dayofYear)
    {
        int vidNumber = 1911; // 公式

        int sum = dayofYear - vidNumber;

        return sum;           
    }

    // 英文轉中文(星期)
    string weekEngToChin(string dayOfWeek)
    {
        string chinWeek = "";

        if (dayOfWeek.ToString().Equals("Monday"))
            chinWeek = "一";
        if (dayOfWeek.ToString().Equals("Tuesday"))
            chinWeek = "二";
        if (dayOfWeek.ToString().Equals("Wednesday"))
            chinWeek = "三";
        if (dayOfWeek.ToString().Equals("Thursday"))
            chinWeek = "四";
        if (dayOfWeek.ToString().Equals("Friday"))
            chinWeek = "五";
        if (dayOfWeek.ToString().Equals("Saturday"))
            chinWeek = "六";
        if (dayOfWeek.ToString().Equals("Sunday"))
            chinWeek = "日";

        return chinWeek;
    }
}


------------------------- 圖片顯示 --------------------

結果顯示: Excel 建立班表格式


2021年3月8日 星期一

跟隨物件

可使用子彈跟蹤
----------------------------

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

public class Bullet_Missile : MonoBehaviour
{

    private Transform targetTr;   // 跟隨物件
    public float dist = 5f;
    public float height = 5.0f;
    public float dampTrace = 10.0f;

    // Update is called once per frame
    void Update()
    {
        targetTr = GameObject.Find("Planet").transform;

        transform.position = Vector3.Lerp(transform.position, targetTr.position - (targetTr.forward * dist) + (Vector3.up * height), Time.deltaTime * dampTrace);
        transform.LookAt(targetTr.position);
    }
}