目前分類:unity C# (26)

瀏覽方式: 標題列表 簡短摘要

使用 Visual Studio Code 編譯C# 方法:

  • 再來  Visual Studio Code 新增資料夾到工作區


 
 
 
 
 
 
 
 
 
 
  • 終端機 打上: dotnet new console

 
 
 
 
 
 
  • 終端機會開始執行

 
  • 就能進行撰寫 C#

 

 

 

 

 

 

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

這邊程式碼,只張貼過程程式碼。

GitHub 專案

OnClickView 類別 (計算過程)

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

public class OnClickView : CalculatoOnClck
{
    private bool active = false;

    // 顯示計算過程
    private static string PROCESS, RESULT, VALUE;

    private static double A, SUM;   
    private bool acrive = false;
    private static string CHEAR_MESSAGE;  //CHEAR_MESSAGE;
    private static int CHEAR_STATUS;    // CHEAR_STATUS

    // 計算過程
    public static string RESULT_PROCESS()
    {
        return "過程: " + PROCESS;
    }

    // 計算結果
    public static string RESULT_()
    {
        return "結果:" + RESULT;
    }

    // 數學符號
    void chear(string chear)
    {
        active = true;
        CHEAR_MESSAGE = chear;

        if (PROCESS.Substring(PROCESS.Length) != CHEAR_MESSAGE)
            PROCESS += CHEAR_MESSAGE;       
    }

    // 數字訊息
    void numberMessage(double conNumber)
    {
        if (active == true)
        {
            PROCESS = "0";
            active = false;
        }

        if (RESULT == null || RESULT == "")    
            PROCESS += conNumber;            
        else   
            PROCESS = RESULT + CHEAR_MESSAGE + conNumber;
        
        VALUE += conNumber;
    }

    public void addClick()
    {
        chear("+");
        CHEAR_STATUS = 1;

        if (RESULT == null || RESULT == "")
            A = double.Parse(VALUE);
        else
            A = double.Parse(RESULT);           
           
        VALUE = "0";        
    }

    public void chearClick()
    {
        throw new System.NotImplementedException();
    }

    public void eightClick()
    {
        numberMessage(8);
    }

    public void equalClick()
    {
        if (CHEAR_STATUS == 1)        
            SUM = A + double.Parse(VALUE);      
        
        if (CHEAR_STATUS == 2)
            SUM = A - double.Parse(VALUE);
  
         if (CHEAR_STATUS == 3)
            SUM = A * double.Parse(VALUE);

         if (CHEAR_STATUS == 4)         
            SUM = A / double.Parse(VALUE);        

        RESULT = SUM.ToString();
    }

    public void fiveClick()
    {
        numberMessage(5);
    }

    public void fourClick()
    {
        numberMessage(4);
    }

    public void nineClick()
    {
        numberMessage(9);
    }

    public void oneClick()
    {
        numberMessage(1);
    }

    public void reduceClick()
    {
        chear("-");
        CHEAR_STATUS = 2;

        if (RESULT == null || RESULT == "")
            A = double.Parse(VALUE);
        else A = double.Parse(RESULT);

        VALUE = "0";
    }

    public void removeClick()
    {
        chear("÷");
        CHEAR_STATUS = 4;

        if (RESULT == null || RESULT == "")
            A = double.Parse(VALUE);
        else A = double.Parse(RESULT);

        VALUE = "0";
    }

    public void sevenClick()
    {
        numberMessage(7);
    }

    public void sixClick()
    {
        numberMessage(6);
    }

    public void takeClick()
    {
        chear("×");
        CHEAR_STATUS = 3;

        if (RESULT == null || RESULT == "")
            A = double.Parse(VALUE);
        else A = double.Parse(RESULT);

        VALUE = "0";
    }

    public void threeClick()
    {
        numberMessage(3);
    }

    public void twoClick()
    {
        numberMessage(2);
    }

    public void zeroClick()
    {
        numberMessage(0);
    }
}

結果圖:

 

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

Unity 練習UI 腳本,因此做了一個小型居家照顧小工具,主要家人工作關係,都要計算,就拿來當練習玩玩。

專案會持續更新.....會弄到導航計算公里數功能。

專案 GitHub

顯示結果:

本文 只提供場景的UI 功能程式。

主頁

Main

MainInterface 腳本:

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

public class MainInterface
{
    private Image buttonArea;
    private RectTransform area;

    ImageSetting buttonAreaSetting;
    AreaSetting areaSetting;

    public MainInterface(Image buttonArea, RectTransform area)
    {
        this.buttonArea = buttonArea;
        this.area = area;
    }

    public void buttonArea_Layout()
    {
        buttonAreaSetting = new ImageSetting(buttonArea, 1f, 1f, 1.6f, 1.6f);
        buttonAreaSetting.function(null, false, true, area);

        // buttonArea 物件底下子物件
        area.transform.parent = buttonArea.transform;

        areaSetting = new AreaSetting(area, new Vector2(0, 0), new Vector2(1, 1), new Vector2(0.5f, 0.5f));
        areaSetting.function(TextAnchor.MiddleCenter, false, false, false, false, true, true);
    }
}

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

服務時間計算

ServiceTime

ServiceInterface 腳本:

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

public class ServiceInterface
{
    private RectTransform manage;    
    private Text hour, minute, titleMessage, serviceMessage;
    private InputField hourInput, minuteInput, serviceInputField;

    AreaSetting manageSetting;
    TextSetting titleMessageSetting;

    InterfaceSetting hourSetting, minuteSetting, servicesSetting;

    private Image breakGroud;
    private Image breaGroudArea;

    ImageSetting breakGroudSetting;
    ImageSetting breakGraoudAreaSetting;

    public ServiceInterface(RectTransform manage, Text titleMessage, 
        Text hour, InputField hourInput, Text minute, InputField minuteInput)
    {
        this.manage = manage;
        this.titleMessage = titleMessage;
        this.hour = hour;
        this.hourInput = hourInput;
        this.minute = minute;
        this.minuteInput = minuteInput;
    }

    public ServiceInterface(Image breakGroud, Image breaGroudArea, RectTransform manage)
    {
        this.breakGroud = breakGroud;
        this.breaGroudArea = breaGroudArea;
        this.manage = manage;
    }

    public ServiceInterface(RectTransform manage, Text serviceMessage, InputField serviceInputField)
    {
        this.manage = manage;
        this.serviceMessage = serviceMessage;
        this.serviceInputField = serviceInputField;
    }

    public void breakGroud_Layout()
    {
        breakGroudSetting = new ImageSetting(breakGroud, 1f, 1f, 1.6f, 1.6f);
        breakGroudSetting.function(null);

        // breakGroudArea 物件底下子物件
        breaGroudArea.transform.parent = breakGroud.transform;

        breakGraoudAreaSetting = new ImageSetting(breaGroudArea, 1f, 1.4f, 1.6f, 0.8f);
        breakGraoudAreaSetting.function(null, false, true, manage);

        // breaGroudArea 物件底下子物件
        manage.transform.parent = breaGroudArea.transform;

        manageSetting = new AreaSetting(manage, Vector2.zero, new Vector2(1, 1), new Vector2(0.5f, 1));
        manageSetting.defaultFunction(new Vector2(0, Screen.height / 2 * 0.8f));
    }

    // 服務次數
    public void serviceTime_Layout(Font font, float pointY)
    {
        manageSetting = new AreaSetting(manage, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f));
        manageSetting.defaultFunction(Vector2.zero);

        servicesSetting = new InterfaceSetting(serviceMessage, serviceInputField, font);
        servicesSetting.funtcionHoliday("服務次數", pointY, Color.green);

        serviceMessage.transform.parent = manage.transform;
        serviceInputField.transform.parent = manage.transform;
    }

    public void serverTime_Layout(Font font, float pointY, string title)
    {
        manageSetting = new AreaSetting(manage, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f));
        manageSetting.defaultFunction(Vector2.zero);

        titleMessageSetting = new TextSetting(titleMessage, 0.6f, pointY, 0.58f, 0.1f); 
        titleMessageSetting.function(font, FontStyle.Normal, title, TextAnchor.MiddleLeft, Color.green, 7);

        hourSetting = new InterfaceSetting(hour, hourInput, font);
        hourSetting.dateWeekfunction("小時", pointY - 0.16f, Color.red);

        minuteSetting = new InterfaceSetting(minute, minuteInput, font);
        minuteSetting.dateWeekfunction("分鐘", pointY - 0.36f, Color.red);

        // manage 物件底下子物件
        titleMessage.transform.parent = manage.transform;
        hour.transform.parent = manage.transform;
        hourInput.transform.parent = manage.transform;
        minute.transform.parent = manage.transform;
        minuteInput.transform.parent = manage.transform;
        titleMessage.transform.parent = manage.transform;     
    }

    public int getServiceValue()
    {
        if (serviceInputField.text == "")
            return 1;

        return Int32.Parse(serviceInputField.text);
    }

    public int getMinuteValue()
    {
        if (minuteInput.text == "")
            return 0;

        return Int32.Parse(minuteInput.text);
    }

    public int getHourValue()
    {
        if (hourInput.text == "")
            return 0;

        return Int32.Parse(hourInput.text);
    }
}

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

單位換算

TimeConvert

TimeConversionInterface 腳本:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System;
using UnityEngine.Events;
public class TimeConversionInterface 
{
    private Text hour, minute, calculatorProcess, calculatorResult;
    private InputField hourInput, minuteInput;
    private RectTransform hourManage, minuteMange, calculatorArea;

    AreaSetting hourMangeSetting, minuteMangeSetting, calculatorAreaSetting;

    InterfaceSetting hourSetting, minuteSetting;

    public TimeConversionInterface(RectTransform hourManage, Text hour, InputField hourInput,
        RectTransform minuteMange, Text minute, InputField minuteInput)
    {
        this.hourManage = hourManage;
        this.hour = hour;        
        this.hourInput = hourInput;

        this.minuteMange = minuteMange;
        this.minute = minute;
        this.minuteInput = minuteInput;
    }

    private Image breakGroud, instructionBreakGroud;
    private Text instruction;

    ImageSetting breakGroudSetting, instructionBreakGroudSetting;
    TextSetting instructionSetting;

    public TimeConversionInterface(Image breakGroud, Image instructionBreakGroud, Text instruction)
    {
        this.breakGroud = breakGroud;
        this.instructionBreakGroud = instructionBreakGroud;
        this.instruction = instruction;
    }
  
    TextSetting calculatorProcessSetting, calculatorResultSetting;

    public TimeConversionInterface(Image breakGroud, RectTransform calculatorArea, Text calculatorProcess, Text calculatorResult)
    {
        this.breakGroud = breakGroud;
        this.calculatorArea = calculatorArea;
        this.calculatorProcess = calculatorProcess;
        this.calculatorResult = calculatorResult;
    }

    private Button button1, button2, button3, button4;
    ButtonSetting button1Setting, button2Setting, button3Setting, button4Setting;

    public TimeConversionInterface(Button button1, Button button2, Button button3, Button button4)
    {
        this.button1 = button1;
        this.button2 = button2;
        this.button3 = button3;
        this.button4 = button4;
    }

    public void calculatorHorizontalBtns(float pointY, Font font, string btnStr1, string btnStr2, string btnStr3,  string btnStr4,
        UnityAction unityAction1, UnityAction unityAction2, UnityAction unityAction3, UnityAction unityAction4)
    {
        button1Setting = new ButtonSetting(button1, 0.4f, 0.7f + pointY, 0.3f, 0.15f, unityAction1);
        button1Setting.function(font, FontStyle.Normal, btnStr1, TextAnchor.MiddleCenter, Color.black, 7);

        button2Setting = new ButtonSetting(button2, 0.8f, 0.7f + pointY, 0.3f, 0.15f, unityAction2);
        button2Setting.function(font, FontStyle.Normal, btnStr2, TextAnchor.MiddleCenter, Color.black, 7);

        button3Setting = new ButtonSetting(button3, 1.2f, 0.7f + pointY, 0.3f, 0.15f, unityAction3);
        button3Setting.function(font, FontStyle.Normal, btnStr3, TextAnchor.MiddleCenter, Color.black, 7);

        button4Setting = new ButtonSetting(button4, 1.6f, 0.7f + pointY, 0.3f, 0.15f, unityAction4);
        button4Setting.function(font, FontStyle.Normal, btnStr4, TextAnchor.MiddleCenter, Color.black, 7);
    }

    // 計算機介面
    public void calculayoutSetting(Font font, float povitY, int textSize)
    {
        breakGroudSetting = new ImageSetting(breakGroud, 1f, 0.6f, 1.6f, 0.66f);
        breakGroudSetting.function(null, false, true, calculatorArea);

        calculatorAreaSetting = new AreaSetting(calculatorArea, Vector2.zero, new Vector2(1, 1), new Vector2(0.5f, 1f));
        calculatorAreaSetting.defaultFunction(new Vector2(1, Screen.height / 2 * povitY));

        // 顯示過程
        calculatorProcessSetting = new TextSetting(calculatorProcess, 1f, 0.86f, 1.5f, 0.1f);
        calculatorProcessSetting.function(font, FontStyle.Normal, "", TextAnchor.MiddleLeft, Color.black, 7);

        // 顯示計算後結果
        calculatorResultSetting = new TextSetting(calculatorResult, 1f, 0.76f, 1.5f, 0.1f);
        calculatorResultSetting.function(font, FontStyle.Normal, "", TextAnchor.MiddleLeft, Color.black, 7);

    }

    // 背景
    public void breakGroud_Layout(string instructionMessage)
    {
        breakGroudSetting = new ImageSetting(breakGroud, 1f, 1f, 1.6f, 1.6f);
        breakGroudSetting.function(null);

        instructionBreakGroudSetting = new ImageSetting(instructionBreakGroud, 1f, 1.59f, 1.6f, 0.42f);
        instructionBreakGroudSetting.function(null, false, true, instruction.rectTransform);

        // instructionBreakGroud 物件底下子物件
        instruction.transform.parent = instructionBreakGroud.transform;

        instructionSetting = new TextSetting(instruction, 0, 0, 0, 0.74f);
        instructionSetting.function(7, instructionMessage, new Vector2(0, 0f), new Vector2(1, 1), new Vector2(0.5f, 1f));
    }

    // 小時與分鐘
    public void hourAndminute(Font font, float pointY)
    {
        hourMangeSetting = new AreaSetting(hourManage, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
            new Vector2(0.5f, 0.5f));
        hourMangeSetting.defaultFunction(Vector2.zero);

        // hourManage 物件底下子物件
        hour.transform.parent = hourManage.transform;
        hourInput.transform.parent = hourManage.transform;

        hourSetting = new InterfaceSetting(hour, hourInput, font);
        hourSetting.dateWeekfunction("小時", pointY, Color.red);

        minuteMangeSetting = new AreaSetting(minuteMange, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f),
            new Vector2(0.5f, 0.5f));
        minuteMangeSetting.defaultFunction(Vector2.zero);

        // minuteMange 物件底下子物件
        minuteMange.transform.parent = minuteMange.transform;
        minuteInput.transform.parent = minuteMange.transform;

        minuteSetting = new InterfaceSetting(minute, minuteInput, font);
        minuteSetting.dateWeekfunction("分鐘", pointY - 0.15f, Color.red);
    }

    public int getHourValue()
    {
        if (hourInput.text == "")
            return 0;

        return Int32.Parse(hourInput.text);
    }

    public int getMinuteValue()
    {
        if (minuteInput.text == "")
            return 0;

        return Int32.Parse(minuteInput.text);
    }
}

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

週次計算

 

WeekTimeConvert

InterfaceObj 腳本:

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

public abstract class InterfaceObj
{
    protected Text message;
    protected InputField inputFiled;
    protected Font font;

    public InterfaceObj(Text message, InputField inputFiled, Font font)
    {
        this.message = message;
        this.inputFiled = inputFiled;
        this.font = font;
    }

    public abstract void dateWeekfunction(string textMessage, float pointY);
    public abstract void funtcionHoliday(string textMessage, float pointY);

    public abstract void systemAndYear(string textMessage, float pointX);
}

InterfaceSetting 腳本:

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

public class InterfaceSetting : InterfaceObj
{
    public InterfaceSetting(Text messge, InputField inputFiled, Font font) : base(messge, inputFiled, font) { }

    TextSetting textSetting;
    InputFieldSetting inputFieldSetting;

    // 週次
    public override void dateWeekfunction(string textMessage, float pointY)
    {
        textSetting = new TextSetting(message, 0.5f, pointY, 0.3f, 0.1f);
        textSetting.function(font, FontStyle.Normal, textMessage, TextAnchor.MiddleLeft, Color.red, 7);

        inputFieldSetting = new InputFieldSetting(inputFiled, 1.15f, pointY + 0.01f, 0.9f, 0.1f);
        inputFieldSetting.function(font, FontStyle.Normal, TextAnchor.MiddleLeft, Color.black, 11,
            InputField.ContentType.IntegerNumber);
    }

    // 假期
    public override void funtcionHoliday(string textMessage, float pointY)
    {
        textSetting = new TextSetting(message, 0.65f, pointY, 0.6f, 0.1f);
        textSetting.function(font, FontStyle.Normal, textMessage, TextAnchor.MiddleLeft, Color.red, 7);

        inputFieldSetting = new InputFieldSetting(inputFiled, 1.28f, pointY + 0.01f, 0.64f, 0.1f);
        inputFieldSetting.function(font, FontStyle.Normal, TextAnchor.MiddleLeft, Color.black, 11,
            InputField.ContentType.IntegerNumber);
    }

    // 年與月
    public override void systemAndYear(string textMessage, float pointX)
    {
        textSetting = new TextSetting(message, pointX, 1.89f, 1f, 0.13f);
        textSetting.function(font, FontStyle.Normal, textMessage, TextAnchor.MiddleLeft, Color.red, 7);

        inputFieldSetting = new InputFieldSetting(inputFiled, pointX - 0.65f, 1.89f, 0.3f, 0.12f);
        inputFieldSetting.function(font, FontStyle.Normal, TextAnchor.MiddleLeft, Color.black, 11,
            InputField.ContentType.IntegerNumber);
    }
}
文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

外部 Dll 都屬於非Unity的套件,加上Unity API 依賴 .net 架構,所以每一個版本Unity 支援的 .NET 版本 會有些不同。

因此 我們要對於專案的設定如下:

※ 匯入Dll 檔案,非Unity內部功能,會導致錯誤,因此要更改。

Unity 2019 LTS - 2020 做法: 

image

Unity 環境下執行可正常,發佈不正常的情況下,大多數都是缺少:

  • I18N.CJK.dll
  • I18N.dll
  • I18N.MidEast.dll
  • I18N.Other.dll
  • I18N.Rare.dll
  • I18N.West.dll

那些dll檔案在Unity 安裝路徑下都能找的到,以下路徑 2019 LTS 路徑

路徑:  C:\Program Files\Unity 2019.4.34f1\Editor\Data\MonoBleedingEdge\lib\mono\unityjit

就能尋找的到了。

 

 

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

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

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

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;
    }
}

---------

專案設定 :

※ 匯入Dll 檔案,非Unity內部功能,會導致錯誤,因此要更改。

Unity 2019 LTS - 2020 做法: 

image

設計介面:

  • 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

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

常常看到手機遊戲都有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# 腳本

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>();
        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

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

又嘗試用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 : "";
    }
}

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

專案設定 :

※ 匯入Dll 檔案,非Unity內部功能,會導致錯誤,因此要更改。

Unity 2019 LTS - 2020 做法: 

image

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

之前文章 簡易的程式碼,之後要管理會變成相當複雜,因此修改了設計方式,之後比較好維護跟操作。

Calendar 腳本(參數管理):

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 腳本(方法撰寫):

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 腳本(執行):

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);
        }
    }
}


結果圖:

image

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

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

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

1. 時間方式計算

2.數字累加

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

邏輯:   數字: 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);

    }
}

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

Unity 資料寫入MySql做法,大致上兩種做法,一種是透過PHP方式來當媒介方式,進行寫入。

另一種則是透過MySQL Community提供Dll 方式直接寫入。

此篇介紹就是以MySQL Community提供Dll方式來進行實踐,但是會有一些版本的問題存在,此篇 Unity 2018版本

MySQL Community 可到這個網站下載,但是要測試可以用的版本~

為了方面實踐,以下我提供兩個載點:

載點1

載點2  提取码:nunc (也可以掃以下二維碼下載)

CD9527EDCD234A2BC1CBE2FFC085627C

再來就是我們要下載 Xampp了,之記得安裝正確。

Xampp 載點

安裝結束後,打開軟體會呈現這個畫面

螢幕擷取畫面 2021-08-05 045747

再點Admin開啟Mysql 網頁版,建立資料庫與資料表,可以查看Mysql 指令方式來建立。

Mysql 指令許多網站都有整理出來:  凍仁大大整理的筆記之分享(MySql 指令)~~

再此 感謝整理Mysql指令大大的辛苦。

建立資料庫與資料表後,呈現以下圖片 (此篇只建立 ID與姓名)

螢幕擷取畫面 2021-08-05 045747

再來就是程式部分了。

本篇習慣介面物件,都以程式方式來撰寫,比較不會到介面下,進行操作調整。

ScriptName: InterfaceObj  介面物件設定

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

public class InterfaceObj : MonoBehaviour
{
    // 輸入介面
    public InputField inputField(InputField inputField, float pointX, float pointY, float sizeX, float sizeY)
    {
        inputField.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
        inputField.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);

        return inputField;
    }

    // 文字顯示
    public Text text(Text text, string message, float pointX, float pointY, float sizeX, float sizeY)
    {
        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);

        text.text = message;
        text.fontSize = 16;
        text.fontStyle = FontStyle.Normal;
        text.color = Color.black;

        return text;
    }

    // 按鈕
    public Button button(Button button, string btnMessage, UnityAction onClick, float pointX, float pointY, float sizeX, float sizeY)
    {
        button.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height / 2 * pointY);
        button.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);

        Text buttonName = button.transform.GetChild(0).GetComponent<Text>();
        buttonName.name = "buttonName";
        buttonName.text = btnMessage;

        button.onClick.AddListener(onClick);

        return button;
    }
}

程式注意: 

using UnityEngine.Events; 要記得匯入,不然按鈕無法進行探聽事件。

  •   UnityAction onClick
  •   button.onClick.AddListener(onClick);

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

Script Name: Layout 介面執行

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

public class Layout : InterfaceObj
{
    // 介面物件
    public Button enter_btn;
    public InputField name_Input;
    public Text name_Text;
    public Text disPlayMessage;

    // 輸入數值
    private string name;

    // 查詢介面物件
    public InputField inquireName_Input;
    public Text inquireName_Text;
    public Button inquireEnter_Button;
    public Text inquireDisPlayerMessage;

    // 查詢名稱
    private string inquireName;

    // 資料表名稱
    private string tableName = "member";

    public float pointX, pointY;

    private void Start()
    {
        text(name_Text, "姓名", 0.16f, 1.78f, 0.1f, 0.1f);
        button(enter_btn, "確定", enter_OnClick, 0.79f, 1.8f, 0.3f, 0.15f);

        // 查詢
        text(inquireName_Text, "姓名", 0.16f, 1.23f, 0.1f, 0.1f);
        button(inquireEnter_Button, "查詢", inquireEnter_OnClick, 0.8f, 1.24f, 0.3f, 0.15f);
    }

    private void Update()
    {
        name = inputField(name_Input, 0.43f, 1.8f, 0.4f, 0.15f).text;
        
        // 判斷是否輸入
        if (name_Input.text == "")
            enter_btn.interactable = false;
        else enter_btn.interactable = true;
        
        text(disPlayMessage, "連接資料庫訊息: " + MySqlClass.result + ",  寫入訊息: " + MySqlClass.disPlayerRead, 1f, 1.55f,1.5f, 0.1f);


        // 查詢
        inquireName = inputField(inquireName_Input, 0.43f, 1.24f, 0.4f, 0.15f).text;

        if (inquireName_Input.text == "")
            inquireEnter_Button.interactable = false;
        else inquireEnter_Button.interactable = true;

        text(inquireDisPlayerMessage, "連接資料庫訊息: " + MySqlClass.result + ",  查詢訊息: " + MySqlClass.disPlayInquire, 1f, 1f, 1.5f, 0.1f);
    }

    // 查詢
    void inquireEnter_OnClick()
    {
        openDataBase();

        MySqlClass.INQUIRE_TABLE(tableName, inquireName);
        MySqlClass.closeSqlConnection();
    }

    void enter_OnClick()
    {
        openDataBase();

        MySqlClass.WriteTable(tableName, name);

        MySqlClass.closeSqlConnection();
    }

    private void OnApplicationQuit()
    {
        MySqlClass.closeSqlConnection();
    }

    void openDataBase()
    {
        string connectionString = string.Format("Server = {0}; Database = {1}; UserID = {2}; Password = {3};", MySqlClass.hostType, MySqlClass.dataBaseType, MySqlClass.idType, MySqlClass.passWordTpye);
        MySqlClass.openSqlConnection(connectionString);
        MySqlClass.myObjType = MySqlClass.GetDataSet(connectionString);
    }
}

程式注意:

OnApplicationQuit(); 關閉應用程式的,主要關閉Mysql 連接,如果有寫執行續(Thread)也需要用到。

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

Script Name:  MySqlClass 執行資料庫動作

using System.Collections.Generic;
using System.Data;
using System;
using MySql.Data.MySqlClient;
using System.Text;
using UnityEngine;

public class MySqlClass
{
    // Just like MyConn.conn in Story Tolls before
    public static MySqlConnection dbConnection;

    // DataBase Ip
    private static string host = "127.0.0.1";
    public static string hostType
    {
        set { host = value; }
        get { return host; }
    }

    // DataBase user Id
    private static string id = "gsp40214";
    public static string idType
    {
        set { id = value; }
        get { return id; }
    }

    // DataBase Password
    private static string passWord = "123456";
    public static string passWordTpye
    {
        set { passWord = value; }
        get { return passWord; }
    }

    // DataBase Name
    private static string dataBase = "pixnet_test";
    public static string dataBaseType
    {
        set { dataBase = value; }
        get { return dataBase; }
    }

    // 連線結果
    public static string result = "";

    // 寫入結果
    public static string disPlayerRead = "";

    // 查詢結果
    public static string disPlayInquire = "";

    // DataSet
    private static DataSet myObj;
    public static DataSet myObjType
    {
        set { myObj = value; }
        get { return myObj; }
    }

    // Connect to database
    public static void openSqlConnection(string connectionString)
    {
        dbConnection = new MySqlConnection(connectionString);
        dbConnection.Open();
        result = dbConnection.ServerVersion;
    }

    // closeSql
    public static void closeSqlConnection()
    {
        dbConnection.Close();
        dbConnection = null;
    }

    // MySQL Query
    public static void doQuery(string sqlQuery)
    {
        IDbCommand dbCommand = dbConnection.CreateCommand();
        dbCommand.CommandText = sqlQuery;
        IDataReader reader = dbCommand.ExecuteReader();
        reader.Close();
        reader = null;
        dbCommand.Dispose();
        dbCommand = null;
    }

    #region Get DataSet
    public static DataSet GetDataSet(string sqlString)
    {
        DataSet ds = new DataSet();

        try
        {
            MySqlDataAdapter da = new MySqlDataAdapter(sqlString, dbConnection);
        }
        catch (Exception e)
        {
            throw new Exception("SQL:" + sqlString + "\n");
            e.Message.ToString();
        }
        return ds;
    }
    #endregion

    // 轉utf8
    public static string messageToUtf8(string message)
    {
        UTF8Encoding encoder = new UTF8Encoding();
        byte[] bytes = Encoding.UTF8.GetBytes(message);
        string utf8ReturnString = encoder.GetString(bytes);

        return utf8ReturnString;
    }

    static string ID;
    static string Message;

    // 寫入資料表
    public static void WriteTable(string DataBaseTable, string message)
    {
        MySqlCommand command = dbConnection.CreateCommand();

        string sqlText = "select count(1) from " + DataBaseTable + " where name=('" + message + "')";

        MySqlCommand cmd1 = new MySqlCommand(sqlText, dbConnection);
        int count = (int)(long)cmd1.ExecuteScalar();

        if (count > 0)
        {
            Debug.Log("已經有資料囉");
            disPlayerRead = "已經有資料囉";

        }
        else
        {         
            Message = messageToUtf8(message);

            command.CommandText = "Insert into " + DataBaseTable + "(id, name) value('" + ID + "','" + Message + "')";
            command.ExecuteNonQuery();

            disPlayerRead = "載入資料成功";
            Debug.Log("載入資料成功");
        }
    }

    // 資料庫查詢
    public static void INQUIRE_TABLE(string dataBaseTitle, string message)
    {
        string sqlText = "select * from " + dataBaseTitle + " where name='" + message + "'";

        MySqlCommand cmd = new MySqlCommand(sqlText, dbConnection);
        MySqlDataReader data = cmd.ExecuteReader();

        while (data.Read())
        {
            try
            {
                disPlayInquire = "資料庫裡面有資料: " + data[1];
            }
            catch (Exception e)
            {
                data.Close();
                closeSqlConnection();
            }
        }

        data.Close();
    }
}

程式注意:

"Insert into " + DataBaseTable + "(id, name) value('" + ID + "','" + Message + "')";  資料庫寫入語法

"select * from " + dataBaseTitle + " where name='" + message + "'";   資料庫查詢語法

 data[1]; 裡面數字代表資料表欄位編號。

如果MySQL有增加新的使用者記得設定權限,否則也會連接失敗。

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

發佈後 執行結果: 

寫入資料庫,記得Mysql 網頁重新整理~

image

如果我們要查詢資料庫是否有小花結果:

image

 

如果發現到發佈之後,無法寫入資料庫,但是在Unity軟體上執行正常,表示缺少Dll 檔案。

缺少檔案: 可以到Unity安裝路徑下:

Unity → Editor → Data → Mono → lib → mono → 2.0 

I18N的相關檔案複製到Unity專案目錄下貼上試試。

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

上一篇 有提到Unity 寫入Excel 基本功能,延續上一篇的方法來實踐有趣的事情吧。

這次 我們會使用Unity UI 功能,來方便設計基本的介面設定。

此篇由程式方式來設定UI設定,比較方便,不用到版面慢慢設定的麻煩。

首先 我們要先知道,我們介面需要使用甚麼物件來進行。

此篇使用物件: Text, InputField, Button

因此建立 UI Class 來方式來撰寫物件設定的功能

Script Name: UIClass

 

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;

public class UIClass : MonoBehaviour
{
    public InputField inputField(InputField obj, float pointX, float pointY, float sizeX, float sizeY){
  
        obj.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height /2 * pointY);
        obj.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);
  
        return obj;
    }
  
    public Text text(Text text, string message, float pointX, float pointY, float sizeX, float sizeY, Color color, int textSize, FontStyle fontStyle){
        
        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);
  
        text.text = message;
        text.fontSize = textSize;
        text.fontStyle = fontStyle;
        text.color = color;
  
        return text;
    }
  
    public Button button(Button button, string button_Name, float pointX, float pointY, float sizeX, float sizeY, UnityAction onClick){
  
        button.transform.position = new Vector2(Screen.width / 2 * pointX, Screen.height /2 * pointY);
        button.image.rectTransform.sizeDelta = new Vector2(Screen.width / 2 * sizeX, Screen.height / 2 * sizeY);
  
        GameObject buttonName = button.transform.GetChild(0).gameObject;
        buttonName.name = "button_Name";
        buttonName.GetComponent<Text>().text = button_Name;
        
        button.onClick.AddListener(onClick);
  
        return button;
    }
}

 

程式部分: 

1. UnityAction - (記得匯入) using UnityEngine.Events; 

※ 由於Unity UI Button 是兩個物件: button與Text物件形成父子物件,為了好分辨,用程式直接進行修改,就不用針對一個一個物件慢慢修改。

2. GameObject buttonName = button.transform.GetChild(0).gameObject;

  •     buttonName.name = "button_Name";
  •     buttonName.GetComponent<Text>().text = button_Name

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

Script Name : Layout

 

using UnityEngine;
using UnityEngine.UI;
using System;

public class Layout : UIClass
{
    public InputField year_inputField, month_inputField, company_inputField;
    public Text year_text, month_text, company_text;
  
    public Button enter_btn, quit_btn;
  
    ClassSchedule classSchedule;
  
    private void Start() {
  
        button_function();
    }
  
    private void Update() {
        layout_();
    }
  
    // 按鈕
    void button_function(){
  
         // 按鈕: 建立班表與應用程式離開
        button(enter_btn, "建立班表格式", 1.3f, 0.3f, 0.3f, 0.2f, Enter_Onclick);
        button(quit_btn, "結束應用程式", 1.7f, 0.3f, 0.3f, 0.2f, Quit_Onclick);
    }
  
    // 介面
    void layout_(){
        
        // 年
        inputField(year_inputField, 0.3f, 1.7f, 0.3f, 0.2f);
        text(year_text, "年", 0.5f, 1.7f, 0.05f, 0.07f, Color.white, 16, FontStyle.Normal);
  
        // 月
        inputField(month_inputField, 0.9f, 1.7f, 0.3f, 0.2f);
        text(month_text, "月", 1.1f, 1.7f, 0.05f, 0.07f, Color.white, 16, FontStyle.Normal);
  
        // 公司名稱
        inputField(company_inputField, 1.65f, 1.7f, 0.3f, 0.2f);
        text(company_text, "公司名稱", 1.36f, 1.7f, 0.14f, 0.07f, Color.white, 16, FontStyle.Normal);
    }
  
    void Enter_Onclick(){
  
        classSchedule = new ClassSchedule(Int32.Parse(year_inputField.text), Int32.Parse(month_inputField.text), company_inputField.text, "行政");
  
        classSchedule.classShedule_Fixed();
    }
  
    void Quit_Onclick(){
        Application.Quit();
    }
}

 

程式部分:

1.  classSchedule = new ClassSchedule(Int32.Parse(year_inputField.text), Int32.Parse(month_inputField.text), company_inputField.text, "行政");

※ 也可以直接進行ClassSchedule 指定參數,不建議使用。

2. button(enter_btn, "建立班表格式", 1.3f, 0.3f, 0.3f, 0.2f, Enter_Onclick);  -  Enter_Onclick : 直接寫成方法來探聽即可。

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

Script Name : classShedule_Fixed

 

using System;
using System.IO;
using OfficeOpenXml;
using Drawing = System.Drawing;

public class ClassSchedule
{
    private int _year, _month;
    private string _companyName, _unit;
   
    public ClassSchedule(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 filePath;                                             
  
    // Excel 固定格式
    int companyNameYear = 1;  // 年
    int positionNumber = 2;  // 職位
    int dayExcelNuber = 3;   // 天
  
    // excel 組件
    ExcelPackage excelPackage;
    ExcelWorksheet workSheets;
  
    // 每年每月類別
    QueryMonthAndDays queryMonthAndDays;
  
    // 檔案類別
    FileInfo fileInfo;
  
    public void classShedule_Fixed(){
  
        // 建立資料夾與檔案位置
        createExcelFile();
  
        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, 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, Drawing.Color.Red);
  
            //加班
            workSheets.Cells[dayExcelNuber, Int32.Parse(dayweekData.day) + 3].Value = "加班";
        }
  
        excelStyle(companyNameYear, 1, dayExcelNuber, queryMonthAndDays.getData().Count + 3);
        excelPackage.Save();
    }
        // excel 樣式
    void excelStyle(int fromRow, int fromCol, int toRow, int toCol)
    {
        // 字形
        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, toCol].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
        workSheets.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Top.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
        workSheets.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Left.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
        workSheets.Cells[fromRow, fromCol, toRow, toCol].Style.Border.Right.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thin;
    }
  
    // Drawing
    void tableColor(int fromRow, int fromCol, 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;
    }
}

 

程式部分:

1. using Drawing = System.Drawing -  記得Unity 專案匯入System.Drawing.dll 才能執行

2. excelPackage = new ExcelPackage(fileInfo) -  檔案位置

3. workSheets = excelPackage.Workbook.Worksheets.Add(queryMonthAndDays.getData()[0].month + "月") - Excel 活頁簿

4. excelStyle(companyNameYear, 1, dayExcelNuber, queryMonthAndDays.getData().Count + 3) - excelStyle(X位置, Y軸位置, X幾格, Y幾格)

5. excelPackage.Save(); - Excel 寫入後存檔

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

Unity 介面部分

GameObjcet :

  1. Main Camera
  2. EventSystem
  3. Canvas:   
    • Year_text -Text
    • Year_inputField - InputField
    • Month_text - Text
    • Month_inputField - InputField
    • Company_text - Text
    • Company_inputField - InputField
    • Enter_btn - Button
    • Quit_btn - Button

那些物件不用設定任何事情,只需要改名及把Layout 腳本放到Canvas物件中。

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

Layout 腳本顯示Public 物件名稱放入場景物件

再來調整製作過程需要的解析度,本版主習慣用 16:9 的比例來做專案,除非遊戲企劃規定,依據更改。

image

※ 順便一提: 此篇沒有UI 介面設計,單位輸入的,如果使用者需要可以自行加入。

以上設定好後,就可以試試了,以下執行結果。

image

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

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

Unity 底下操作寫入Excel 檔案且匯出xlsx 副檔名,並且需要前置工作,否則匯入dll檔案會導致Unity 錯誤,如果少了dll 檔案發佈專案後,也會導致無法正常輸入Excel 檔案。

當然在正常遊戲設計領域,很少會使用到這項功能,但是 Unity 強項,並非只有在製作遊戲上面哦。

以下來進行,今天主題的內容如何實踐吧~

所先要下載,可以製作Excel方式來進行方便開發。

Excel 全部相關DLL下載   提取碼: 0xso  /  備用載點

所使用的工具 EPPLUS 組件方式,來方便撰寫。

Dll 載入Unity中,會出現一些紅字問題。

如下圖:

image

那個問題是Unity 表示,無法讀取 .Net Standard 2.0 API, 因此需要設定專案。

操作方式為: File/Build Setting....(快捷鍵 : ctrl +shift +b),會出現 Bulid setting 視窗

Visual Studio code 組件圖示

再設定 API Compatibility Level 選項選擇 .Net4.0 (文章Unity 版本: 2018)

Visual Studio code 組件圖示

選擇完後,錯誤紅字就會消失,如果還有出現錯誤請刪除 System.Data.dll 這個檔案即可。

再來 我們就來測試一下是否,可以正常寫入與讀取匯出。

我查詢了許多相關資訊,也是有很多方式,覺得比較複雜,這裡提供簡單方式來進行。

再來就是程式部分了 呵呵~

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

public class ExcelTest : MonoBehaviour
{
    public string filePath = @"C:\Users\user\Desktop\123.xlsx";
    FileInfo fileInfo;
    ExcelPackage package;
    ExcelWorksheet worksheet;
    string str = "";
  private void OnGUI() {      
        
      // 寫入Excel 檔案裏面內容
      if(GUILayout.Button("寫入Excel 檔案內容"))
        writeExcel();
  
      if(GUILayout.Button("讀取 Excel 檔案名稱")){
          str = readExcel();
      }
       
     GUILayout.Label("測試: " + str);
  }
  
  // 讀取 Excel  檔案
  string readExcel(){
      
      string result = "";
  
      fileInfo = new FileInfo(filePath);
  
      package = new ExcelPackage(fileInfo);
  
      worksheet = package.Workbook.Worksheets["Test"];
  
      string str = worksheet.Cells[1, 1].Text;
      string str1 = worksheet.Cells[2, 1].Text;
      string str2 = worksheet.Cells[3, 1].Text;
  
      result = str + str1 + str2;
  
      return result;
  }
  
  // 寫入Excel 檔案
  void writeExcel(){
      
      fileInfo = new FileInfo(filePath);
  
      if(fileInfo.Exists){
  
          fileInfo.Delete();
          fileInfo = new FileInfo(filePath);
        }
  
      fileInfo = new FileInfo(filePath);
      package = new ExcelPackage(fileInfo);
      
      worksheet = package.Workbook.Worksheets.Add("Test");
      
      worksheet.Cells[1, 1].Value = "ID";
      worksheet.Cells[2, 1].Value = "小名";
      worksheet.Cells[3, 1].Value = "小花";
  
      package.Save();
  }
}

程式部分解釋:

Excel 裡面表格,可以看成 X, Y 座標的方式來進行。

string str = worksheet.Cells[1, 1].Text; 

以上那段程式解釋 string 負責接值由worksheet.cells.text 來傳值。

會發現到Cells[1, 1] 裡面顯示1,1 那個表示Excel 表格位置,當然也可以直接寫成Cells[A1],只是不建議就是了。

主要是寫成A1的話,是直接指定,如果多筆資料要一個一個指定較麻煩,不如使用迴圈條件來進行寫入較方便。

這段程式: worksheet = package.Workbook.Worksheets["Test"];  是Excel 活頁簿 ,因此Excel 必要有活頁簿才能進行執行。

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

結果圖如下:

Unity 發佈與未發佈,執行結果是會有差距的。

因此需要發佈執行為主。

Visual Studio code 組件圖示

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

Unity 讀取年月日,並顯並不是難事,只要使用 System.DateTime 函式庫就可以了。

顯示設定當下月份天數,比較少用到這個功能,除非班表功能(讓使用者)才會使用的上。

那我們趕快進入程式碼部分吧

這段程式:  resultDisPlayer(int year, int month, int day) 為了方便使用者開發,

可以透過UI介面或者Unity GUI (過去式介面) 來進行溝通。

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

public class TestScript : MonoBehaviour
{
    DateTime startdate;
  
    // Start is called before the first frame update
    void Start()
    {
        Debug.Log(resultDisPlayer(2021, 5, 1));        
    }
  
    string resultDisPlayer(int year, int month, int day){
  
        string result = "";
  
        startdate = new DateTime(year, month, day);
  
        for (int x = day; x <= DateTime.DaysInMonth(startdate.Year, startdate.Month); x++)
        {
 
            startdate = new DateTime(startdate.Year, startdate.Month, x);
  
            string str = "民國: " + vidToRepublic(startdate.Year) + "年 " 
                + startdate.Month + "月 " + x + "日 " + "星期: " + weekEngToChin(startdate.DayOfWeek.ToString());
  
            result += str + "\n";
        }
  
        return result;
  
    }
  
    // 西元轉換民國 (公式)
    string vidToRepublic(int dayofYear)
    {
        int vidNumber = 1911; // 公式
  
        int sum = dayofYear - vidNumber;
  
        return sum.ToString();           
    }
  
    // 英文轉中文(星期)
    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;
    }
}

顯示結果如下:

image

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

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

如步驟以下:

官方連結:  Visual Studio Code

下載完成後_介面如下:

 

 

 

 

 

 

 

 

 

 

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

官方連結: .NET Core SDK

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

 
 
下載安裝後,在安裝常用組件:
 
 
 
 
 
 
再到Unity3D 軟體,設定程式腳本編譯器選擇
 

 

 
 
 
 
 
 
 
 
 
 
 

 

 

 

 

 

 

 

 

 

出現以下圖片結果表示成功了  

 

 

 

 

 

 

 

若沒辦法顯示,請進行重新開機即可。

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

程式碼來源: https://blog.csdn.net/BIGMAD/article/details/71698310

---- 以下是編輯路徑腳本 ----

 

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

public class EditorPathScript : MonoBehaviour {

    public Color rayColor = Color.red;
    public List path_objs = new List();
    Transform[] theArray;

    void OnDrawGizmos(){
        Gizmos.color = rayColor;
        theArray = GetComponentsInChildren();
        path_objs.Clear();
        foreach(Transform path_obj in theArray){
            if(path_obj != this.transform)
                path_objs.Add(path_obj);
        }

        for(int i = 0;i0){
                Vector3 previous = path_objs[i-1].position;
                Gizmos.DrawLine(previous,position);
                Gizmos.DrawWireSphere(position, 0.3f);
            }
        }
    }
}

 

 

20170511212047659.png

---- 以下是物件跟隨行為腳本 ----

using UnityEngine;
using System.Collections;

public class FollowPath : MonoBehaviour {

    public bool StartFollow = false;
    public EditorPathScript PathToFollow;
    public int CurrentWayPointID = 0;
    public float Speed;//移动速度
    public float reachDistance = 0f;//里路径点的最大范围
    public string PathName;//跟随路径的名字
    private string LastName;
    private bool ChangePath = true;



    void Start () {

    }

    void Update () {
        if (!StartFollow)
            return;
        if (ChangePath)
        {
            PathToFollow = GameObject.Find(PathName).GetComponent();
            ChangePath = false;
        }
        if (LastName != PathName)
        {
            ChangePath = true;
        }
        LastName = PathName;




        float distance = Vector3.Distance(PathToFollow.path_objs[CurrentWayPointID].position, transform.position);
        //transform.Translate(PathToFollow.path_objs[CurrentWayPointID].position * Time.deltaTime * Speed, Space.Self);
        transform.position = Vector3.MoveTowards(transform.position, PathToFollow.path_objs[CurrentWayPointID].position, Time.deltaTime * Speed);
        if (distance &lt;= reachDistance)
        {
            CurrentWayPointID++;
        }
        if (CurrentWayPointID &gt;= PathToFollow.path_objs.Count)
        {
            CurrentWayPointID = 0;
        }
    }
}

 

20170511212205142.png

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

此文章內容則是以Unity來製作Android系統讓手機產生震動的效果。

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

Script (C#):

 

using System.Collections;
using UnityEngine;

public static class Vibration
{
#if UNITY_ANDROID && !UNITY_EDITOR
    public static AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    public static AndroidJavaObject currentActivity = unityPlayer.GetStatic("currentActivity");
    public static AndroidJavaObject vibrator = currentActivity.Call("getSystemService", "vibrator");

#else
    public static AndroidJavaClass unityPlayer;
    public static AndroidJavaObject currentActivity;
    public static AndroidJavaObject vibrator;
#endif

    private static bool isAndroid()
    {
#if UNITY_ANDROID && UNITY_EDTOIR
        return true;
#else
        return false;
#endif
    }

    /// 

    /// 震動
    /// 
    public static void Vibrate()
    {
        if (isAndroid())
            vibrator.Call("vibrate");
        else
            Handheld.Vibrate();      
    }

    /// 

    /// 震動(毫秒)
    /// 
    /// 
    public static void Vibrate(long milliseconds)
    {
        if (isAndroid())
            vibrator.Call("vibrate", milliseconds);
        else
            Handheld.Vibrate();
    }

    /// 

    /// 模式震動
    /// 重覆
    /// 
    /// 
    /// 
    public static void Vibrate(long[] pattern, int repeat)
    {
        if (isAndroid())
            vibrator.Call("vibrate", pattern, repeat);
        else
            Handheld.Vibrate();
    }

    /// 

    /// 判斷是否震動器
    /// 
    /// 
    public static bool HasVibrator()
    {
        return isAndroid();
    }

    /// 

    /// 取消
    /// 
    public static void Cancel()
    {
        if (isAndroid())
            vibrator.Call("cancel");
    }
}

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

此文章內容則是...遊戲設計很常用到的第一人稱,雖然Unity官方也很套件可以使用。

但是自己研究後,發現到滿有趣的,有興趣的玩家,不妨也來試試吧。

此功能有使用到Unity Editor 功能哦,請嘗試玩家注意。

 

詳細資料在於Google Blogger 部落格這裡,請點選

 

以下則是這次內容FPS 程式範例:

FPS (第一人稱) 腳本

mpleSmoothMouseLook (攝影機) 腳本

---------

Script (C#):

using UnityEngine;
using System.Collections;
using UnityEditor;

[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(CapsuleCollider))]

public class FPS : MonoBehaviour {
    
    [MenuItem("PlayerMode/FPS")]
    static void Fps() {
        GameObject fps = new GameObject("FPS");
        fps.transform.position = Vector3.zero;

        // FPS add component
        fps.AddComponent();

        GameObject cam = new GameObject("Camera");
        cam.transform.parent = fps.transform;

        // Camera add component
        cam.AddComponent();
        cam.AddComponent();
        cam.AddComponent();
        cam.AddComponent();
        cam.AddComponent();
    }

    [SerializeField]
    float speed = 10.0f, gravity = 10.0f, maxVelocityChange = 10f, jumpHeight = 2.0f;
    [SerializeField]
    bool canJump = true;

    private bool grounded = false;

    Rigidbody rigidbody;
    CapsuleCollider playerCollider;

    void Awake(){
        rigidbody = GetComponent();
        rigidbody.freezeRotation = true;
        rigidbody.useGravity = false;
        gameObject.AddComponent();
    }

    void FixedUpdate() {

        if (grounded) {

            // Calculate how fast we should be moving
            Vector3 targetVelocity = new Vector3(Input.GetAxis("Horizontal") * speed,0, Input.GetAxis("Vertical")* speed);
            targetVelocity = transform.TransformDirection(targetVelocity);

            // Apply a force that attempts to reach our target velocity
            Vector3 velocity = rigidbody.velocity;
            Vector3 velocityChange = (targetVelocity - 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);

            //Jump
            if (canJump && Input.GetButton("Jump"))
                rigidbody.velocity = new Vector3(velocity.x, CalculateJumpVerticalSpeed(), velocity.z);
        }
        rigidbody.AddForce(new Vector3(0,-gravity * rigidbody.mass, 0));
        grounded = false;
    }

    void OnCollisionStay()
    {
        grounded = true;
    }

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

 

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

Script (C#):

using UnityEngine;
using System.Collections;


[AddComponentMenu("Camera/Simple Smooth Mouse Look ")]
public class SimpleSmoothMouseLook : MonoBehaviour {

    Vector2 _mouseAbsolute;
    Vector2 _smoothMouse;

    public Vector2 clampInDegrees = new Vector2(360, 180);
    public bool lockCursor;
    public Vector2 sensitivity = new Vector2(2, 2);
    public Vector2 smoothing = new Vector2(3, 3);
    public Vector2 targetDirection;
    public Vector2 targetCharacterDirection;

    // Assign this if there's a parent object controlling motion, such as a Character Controller.
    // Yaw rotation will affect this object instead of the camera if set.
    public GameObject characterBody;

    void Start()
    {
        // Set target direction to the camera's initial orientation.
        targetDirection = transform.localRotation.eulerAngles;

        // Set target direction for the character body to its inital state.
        if (characterBody) targetCharacterDirection = characterBody.transform.localRotation.eulerAngles;
    }

    void Update()
    {
        // Ensure the cursor is always locked when set
        Screen.lockCursor = lockCursor;

        // Allow the script to clamp based on a desired target value.
        var targetOrientation = Quaternion.Euler(targetDirection);
        var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);

        // Get raw mouse input for a cleaner reading on more sensitive mice.
        var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));

        // Scale input against the sensitivity setting and multiply that against the smoothing value.
        mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));

        // Interpolate mouse movement over time to apply smoothing delta.
        _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
        _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y);

        // Find the absolute mouse movement value from point zero.
        _mouseAbsolute += _smoothMouse;

        // Clamp and apply the local x value first, so as not to be affected by world transforms.
        if (clampInDegrees.x < 360)
            _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);

        var xRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right);
        transform.localRotation = xRotation;

        // Then clamp and apply the global y value.
        if (clampInDegrees.y < 360)
            _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);

        transform.localRotation *= targetOrientation;

        // If there's a character body that acts as a parent to the camera
        if (characterBody)
        {
            var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, characterBody.transform.up);
            characterBody.transform.localRotation = yRotation;
            characterBody.transform.localRotation *= targetCharacterOrientation;
        }
        else
        {
            var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
            transform.localRotation *= yRotation;
        }
    }
}

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

此文章內容是天氣裡面的龍捲風物理哦。

龍捲風作法,我相信大家都應該知道 可以用粒子系統 (Particle System)及加上旋轉就能形成。

我們馬上來看以下程式碼之範例吧... 

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

Script (C#):

using UnityEngine;
using System.Collections;

public class Tornado_Main : MonoBehaviour {

    [Tooltip(&quot;This controls the radius of your tornados pull range&quot;)]
    public float radius = 65.28f;
    public float maxRadiusToPullIn = 10;
    [Tooltip(&quot;NEGATIVE NUMBERS ONLY. This pulls objects into the tornado&quot;)]
    public float PullingInPower = -70;
    public float MaxPullingIn = 20;

    Collider[] colliders;

    void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(transform.position, radius);
    }
    
    void Update()
    {
        colliders = Physics.OverlapSphere(transform.position, radius);
        foreach (Collider c in colliders)
        {
            if (c.GetComponent() == null)
            {
                continue;
            }
            Ray ray = new Ray(transform.position, c.transform.position - transform.position);
            RaycastHit hit;
            Physics.Raycast(ray, out hit);
            if (hit.collider.name != c.gameObject.name || hit.distance &lt; MaxPullingIn)
            {
                continue;
            }
            else
            {
                Rigidbody rigidbody = c.GetComponent();
                rigidbody.AddExplosionForce(PullingInPower, transform.position, radius);
            }
        }
    }
}

 

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

Script(C#):

using UnityEngine;
using System.Collections;

public class Outer_Tornado : MonoBehaviour
{

    public float radius = 19.48f;
    public float outsideSpeed = 0.7f;
    public float maxPullInLength = 24.96f;
    public float power = 1;


    Collider[] colliders;

    void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(transform.position, radius);
    }

    void Update ()
    {
        transform.RotateAround(transform.parent.transform.position, Vector3.up, outsideSpeed);
        colliders = Physics.OverlapSphere(transform.position, radius);
        foreach (Collider c in colliders)
        {
            if (c.GetComponent() == null)
            {
                continue;
            }
            Rigidbody rigidbody = c.GetComponent();
            Ray ray = new Ray(transform.position, c.transform.position - transform.position);
            RaycastHit hit;
            Physics.Raycast(ray, out hit);
            if (hit.distance &gt; maxPullInLength)
            {
                continue;
            }
            if (c.transform.position.z &gt; 8.5)
            {
                Vector3 Force = new Vector3(transform.position.x - c.transform.position.x, rigidbody.velocity.y / 2, transform.position.z - c.transform.position.z) * power;
                rigidbody.AddForceAtPosition(Force, transform.position);
            }
            rigidbody.AddForceAtPosition((transform.position - c.transform.position) * power, transform.position);
        }
    }
}

 

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

結果圖:

成功的話,可以像以下圖片一樣,讓物件飛起來哦....

111.PNG

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

此文章內容則是物件跟隨,遊戲設計當中,可是很常見的功能。

以下則是此文章範例程式:

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

Script (c#):

 

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

public class PetFlow : MonoBehaviour {

    public Transform player;
    public float maxDis = 5;

    private SmoothFollowerObj posFollow; // 控制位置平滑移動
    private SmoothFollowerObj lookFollow; // 控制朝向平滑轉換

    public Vector3 posistionVector; // 角色位置移動,方向向量
    public Vector3 lookVector; //角色朝向變化,朝向向量

    private Vector3 lastVelocityDir; // 上一次移動方向
    private Vector3 lastPost; // 之前移動目標位置

    void Start()
    {
        posFollow = new SmoothFollowerObj(0.5f, 0.5f);
        lookFollow = new SmoothFollowerObj(0.1f, 0.1f);
        posFollow.Update(transform.position, 0, true); // 初始位置
        lookFollow.Update(player.transform.position, 0, true);

        posistionVector = new Vector3(0, 0.5f, 1.7f);
        lookVector = new Vector3(0, 0, 1.5f);

        lastVelocityDir = player.transform.forward;
        lastPost = player.transform.position;
    }

    void Update()
    {
        float dis = Vector3.Distance(transform.position, player.position);

        if (dis &gt; maxDis)
            PetMoveFlow();
    }

    // 物件移動
    void PetMoveFlow()
    {
        lastVelocityDir += (player.position - lastPost) * 5;
        lastPost = player.position;

        lastVelocityDir += player.transform.forward * Time.deltaTime;
        lastVelocityDir = lastVelocityDir.normalized;

        Vector3 horizontal = transform.position - player.position;
        Vector3 horizontal2 = horizontal;
        Vector3 vertical = player.up;
        Vector3.OrthoNormalize(ref vertical, ref horizontal);  // https://docs.unity3d.com/ScriptReference/Vector3.OrthoNormalize.html api

        // https://docs.unity3d.com/ScriptReference/Vector3-sqrMagnitude.html api
        if (horizontal.sqrMagnitude &gt; horizontal2.sqrMagnitude)
            horizontal = horizontal2;

        transform.position = posFollow.Update(player.position + horizontal * Mathf.Abs(posistionVector.z)
            + vertical * posistionVector.y, Time.deltaTime);

        horizontal = lastVelocityDir;

        Vector3 look = lookFollow.Update(player.position + horizontal * lookVector.z
            - vertical * lookVector.y, Time.deltaTime);

        // https://docs.unity3d.com/ScriptReference/Quaternion.FromToRotation.html api
        transform.rotation = Quaternion.FromToRotation(transform.forward, look - transform.position) * transform.rotation;
    }
}

class SmoothFollowerObj
{
    private Vector3 targetPosistion; // 目標位置
    private Vector3 position; // 位置
    private Vector3 velocity;  // 速率
    private float smoothingTime; // 平滑時間
    private float prediction; // 預測

    public SmoothFollowerObj(float smoothingTime)
    {
        targetPosistion = Vector3.zero;
        position = Vector3.zero;
        this.smoothingTime = smoothingTime;
        prediction = 1;
    }

    public SmoothFollowerObj(float smoothingTime, float prediction)
    {
        targetPosistion = Vector3.zero;
        position = Vector3.zero;
        this.smoothingTime = smoothingTime;
        this.velocity = velocity;
    }

    // 更新位置資訊
    public Vector3 Update(Vector3 targetPosistionNew, float dataTime)
    {
        Vector3 targetvelocity = (targetPosistionNew - targetPosistion) / dataTime; // 獲取目標移動的方向向量
        targetPosistion = targetPosistionNew;

        float d = Mathf.Min(1, dataTime / smoothingTime);
        velocity = velocity * (1 - d) + (targetPosistion + targetvelocity * prediction - position) * d;

        position += velocity * Time.deltaTime;
        return position;
    }

    // 根據傳輸進來數據, 重置本地參數
    public Vector3 Update(Vector3 targetPosistionNew, float dataTime, bool rest) 
    {
        if (rest)
        {
            targetPosistion = targetPosistionNew;
            position = targetPosistionNew;
            velocity = Vector3.zero;

            return position;
        }

        return Update(targetPosistionNew, dataTime);
    }

    public Vector3 GetPosistion() { return position; }
    public Vector3 GetVelocity() { return velocity; }
}

 

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

成功的話....物件會會跟著所指定的位置來做移動哦。

此外...可以利用物件與物件關係(親代)來調整中心點位置。

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

已經好久沒來「痞客邦」來寫關於Unity 技術文章,都在Goolge Blooger 那邊撰寫比較多 

回歸主題...此文章內容是Unity裡面Sprite 裡面的功能。

不多說...直接看程式碼之範例吧

忘了一件事情,此程式碼操作使用到Unity Editor 外掛編輯元件哦。

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

Unity Edtor (C#):

 

 

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

public class SpriteProcessor : EditorWindow
{

    private Vector2 vector2Label;          // 標籤位置(BeginScrollView 用的)
    private GUIStyle style = new GUIStyle();   // GUI 風格
    private string spriteSegmentationType = &quot;&quot;;  // Sprite 分割像素
    private string spriteName = &quot;&quot;;        // Sprite 分格後名稱
    private int spriteTitleNumber = 0;   // 分格後的名稱編號
    private int spriteSegmentationNumber;   // 分割數值字串轉型



    //  呼叫視窗
    [MenuItem(測試/Sprite寫法)]
    public static void spriteWindowSetting()
    {
        SpriteProcessor windows = EditorWindow.GetWindow(typeof(SpriteProcessor), true, &quot;Sprite 自動分割&quot;) as SpriteProcessor;
        windows.Show();
    }

  

    // 選擇貼圖(Sprite)
    static Object[] getSelectTexture()
    {
        return Selection.GetFiltered(typeof(Texture2D), SelectionMode.DeepAssets);
    }

    void OnGUI()
    {

        style.fontSize = 18;
        style.normal.textColor = Color.white;

        GUI.Label(new Rect(0, 0, 100, 30), &quot;圖片分割&quot;, style);

        // Sprite 分割像素
        GUILayout.BeginArea(new Rect(0, 30, 300, 100));
        GUILayout.BeginHorizontal();
        GUILayout.Label(&quot;Sprite 分割像素&quot;);
        GUILayout.EndHorizontal();
        GUILayout.EndArea();

        // Sprite 分割像素輸入
        GUILayout.BeginArea(new Rect(150, 30, 150, 100));
        GUILayout.BeginHorizontal();
        spriteSegmentationType = GUILayout.TextField(spriteSegmentationType);
        GUILayout.EndHorizontal();
        GUILayout.EndArea();

        // Sprite標籤
        GUILayout.BeginArea(new Rect(0, 110, 300, 100));
        GUILayout.BeginHorizontal();
        GUILayout.Label(&quot;Sprite 標簽名稱&quot;);
        GUILayout.EndArea();
        GUILayout.EndHorizontal();

        // Sprite標籤輸入
        GUILayout.BeginArea(new Rect(148, 110, 150, 100));
        GUILayout.BeginHorizontal();
        spriteName = GUILayout.TextField(spriteName);
        GUILayout.EndHorizontal();
        GUILayout.EndArea();

        GUILayout.BeginArea(new Rect(200, 150, 100, 100));
        GUILayout.BeginHorizontal();
        if (GUILayout.Button(&quot;確定&quot;))
            SetPivots();
        GUILayout.EndHorizontal();
        GUILayout.EndArea();
    }
 
    // 分割動作
    void SetPivots()
    {
        spriteTitleNumber = 0;
        // 判斷轉型成功執行分割
        if (int.TryParse(spriteSegmentationType, out spriteSegmentationNumber))
        {
            Object[] textures = getSelectTexture();
            Selection.objects = new Object[0];

            SpriteMetaData d = new SpriteMetaData();
            
            foreach (Texture2D texture in textures)
            {
                string path = AssetDatabase.GetAssetPath(texture);
                TextureImporter ti = AssetImporter.GetAtPath(path) as TextureImporter;
                ti.isReadable = true;
                List newData = new List();
                newData.Remove(d);
                for (int x = 0; x &lt; texture.width; x += spriteSegmentationNumber)
                {
                    for (int y = 0; y &lt; texture.height; y += spriteSegmentationNumber)
                    {
                        d.alignment = 9;
                        d.pivot = new Vector2(0.5f, 0.5f);
                        d.name = spriteName + &quot;_&quot; + (spriteTitleNumber += 1);
                        d.rect = new Rect(x, y, spriteSegmentationNumber, spriteSegmentationNumber);
                        newData.Add(d);
                    }
                }
                ti.spritesheet = newData.ToArray();
                AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
            }
        }
    }
}

 

-------------- 顯示結果圖下

111.PNG

 

 

 

 

 

 

 

文章標籤

Xauxas 發表在 痞客邦 留言(0) 人氣()

1 2