, ,

【Unity】Timeout while trying to pause the Unity Engine 真的只是猜測


這個BUG其實也不知道從何說起,這篇是默認看的人已經知道android java 那些知識了,細節就不加以詳述了,因為大多都是以自己的理解去解釋,沒追證過,如果理解有誤還麻煩告知我XD

BUG點 : Timeout while trying to pause the Unity Engine


引發這個的可能性有很多,這裡只談到我遇到的這一種

當視窗沒有失焦,然後你可能使用了任何一個改變視窗的function((像是投影到電腦)),在這之後,如果單純觸發了activity的onPause方法沒有讓onWindowChangeFocus一起被觸發的話,在onResume的時候,unity就會當掉了,這時候如果又要onPause Unity的話就會出現

Timeout while trying to pause the Unity Engine. 




這裡是我解這bug幾天的心得,可能跟事實不一定完全相同,知識點可能也有誤,可以看看就好。

Unity內有許多系統的function ,其中有個 OnApplicationPause 跟 onApplicationfocus

官方連結:


OnApplicationFocus他是在UnityPlayerActivity內的 onWindowChangeFocus上觸發的,((如果我沒記錯的話)),然後OnApplicationPause也是UnityPlayerActivity內的 onPause 去觸發的

其中onWindowChangeFocus這個很重要,他是在渲染完成的時候調用的

當現在你的螢幕視窗被改變了,像是miracast到電腦,如果你沒觸發mUnityPlayer.windowChangeFocus讓unity去改變底層的東西,就直接pause他並resume的話就會出現問題,所以在pause之前(或之後?) 必須call [mUnityPlayer.windowChangeFocus ] ((這裡是嚴重的猜測,很不一定是真的))




Share:
Read More

【Unity】製作AndroidPlugin的重點與可能遇到的坑



有時候使用unity的時候會想要更改或使用到android內建的東西,像是android的鍵盤、android的通知欄(Toast)
這個時候單單使用unity能做到的事是有限的,所以必須使用android的plugin才能解決這類的問題


PluginsForAndroid 官方這邊就可以看到了
https://docs.unity3d.com/Manual/PluginsForAndroid.html

android plugin 的兩種格式


一個是用jar檔一個是aar檔,兩個都可以在unity內使用

兩者區別是:
jar檔只包含純code的模式,以下示意圖,每個jar檔可能都不一樣,當然還包含一些目錄的文件夾









aar檔則是有包含布局阿、圖檔阿...等這個plugin用到的資源,看起來像這樣







Unity官方則是推薦使用aar來當作plugin使用


製作android plugin的文章已經很多了,這邊講一下比較重要跟比較容易遇坑的幾點


導入classes (UNITY內的)


unity有提供一個jar檔作為android 與 unity的橋樑,
大致路徑是C:\Program Files\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes

ps.如果最後輸出的是aar檔,最後要將aar檔內的libs/classes.jar刪除,以免與unity重複打包

app資料夾內build.gradle內


1. apply plugin: 'com.android.application'改成apply plugin: 'com.android.library' //因為是要當成plugin使用,所以要將application改成library,不然會輸出成apk

2. applicationId "com.xx.xxxxx" //這一行刪除

3. dependencies內新增compile files('libs/classes.jar')  //後面這個路徑是unity plugin接入的路徑跟檔名

4. minSdkVersion 21 對應到 unity BuildSetting內的MinimumAPI  LEVEL (下面有)

AndroidManifest


這個是一個xml檔案,用來指向unity連接android的入口與一些app屬性的操作,像是
裡面比較重要的是packgeName ,unity BuildSetting內的packgeName要跟AndroidManifest內的packgeName一樣,minSdkVersion 也必須跟BuildSetting內MinimumAPI Level一樣 (見下圖)







<meta-data android:name="unityplayer.UnityActivity" android:value="true"/>

放在</intent-filter>下面 </activity>上面

完整版:


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.u2a.testconnect" >


  <application
     
      android:label="@string/app_name"  // 如果你打沒這行,你在unity build出來的app名字會跟你在productName設定的不相符
      android:theme="@android:style/Theme.NoTitleBar">
    <activity android:name="com.u2a.testconnect.MainActivity">
      <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
    </activity>

  </application>

</manifest>

如果製作jar檔,可能會遇到的坑

上面一經贅述了很多,至於怎麼製作jar檔,參考連結應該會有,筆者爬了很多製作jar檔的方式,發現有個小坑,會讓你按export jar之後,資料夾與jar檔都沒出現在目錄上






















對,就是gradle的版本,默認情況下會使用2.3.3版本,可是這樣照著網路上的資料來做的話,並不會出現想要的jar檔,我是改成2.2.3之後重build一次才出現jar檔的。




Extra: ((由於不多,所以不想多占一篇))

接上unity的plugin後,通常都會在MainActivity繼承UnityPlayerActivity (( 當然其他的Activity也可以,但是記得AndroidMainfest上的入口要修改為你用UnityPlayerActivity的那個 )),那這時已經建立連接口了,創建其他Activity的時候就不用再import UnityPlayerActivity了,除非有特殊需求,而如果要在unity內讀取其他Activity的話,則只需要使用AndroidJavaClass來指定讀取的路徑就可以了,像是我的packgeName為com.u2a.testconnect,第二個Activity 叫做SecondActivity,裡面有個靜態方GetSecondActivityNumber,回傳一個int,則會寫成這樣

Code:

  public Text log;
    int secondActivityNum = 0;

    private void OnGUI()
    {
      

        if (GUI.Button(new Rect(50, 500, 200, 100), "呼叫 SecondActivity的GetNumber"))
        {
           
            using ( AndroidJavaClass unity = new AndroidJavaClass("com.u2a.testconnect.SecondActivity")) //找出packge內的SecondActivity類別
            {
                secondActivityNum =   unity.CallStatic<int>("GetSecondActivityNumber");
                ShowSecondActivityNum();
            }

        }
        
    }

    public void ShowSecondActivityNum()
    {
        log.text = "顯示的數字(預設0) :"+secondActivityNum;
    }



關於 UnityPlayer.UnitySendMessage 看一下文件使用方法就知道了,這邊就不再多說。


成品:GOOGLE雲端


如果上述文章有任何疑問或錯誤理解,請不用懷疑的留言告知我,感謝。


參考資料與延伸閱讀:

Android Activity與 UnityPlayer Activity
http://eppz.eu/blog/unity-android-plugin-tutorial-1/


Android和Unity混合开发——Activity和Unity脚本交互和信息传递
http://www.jianshu.com/p/a7d82b3ac0c4

Android studio中如何生成引用 .aar 和 .jar
http://www.jianshu.com/p/76559da9ab39


Android Studio导出并使用aar和jar
http://chiahaolu.github.io/2016/06/27/Android-Studio%E5%AF%BC%E5%87%BA%E5%B9%B6%E4%BD%BF%E7%94%A8aar%E5%92%8Cjar/


Android Studio 打包及引用 aar
http://www.androidchina.net/2467.html






Share:
Read More
,

【C# 讀書會簡報】

由於前一陣子有朋友幾個人開讀書會複習
做了挺多個的
用完擺著不看也是浪費
所以就分享出來啦~
有錯的煩請下面留言說一下
一起學習~


===

類別、封裝

多載、屬性

匿名委派、Lambda

這邊有許多錯字,基本上看英文比較實在XD,我那時候查也一堆序、續、緒搞不清楚
執行序

LinQ
Share:
Read More
,

【Unity】xml文件讀取

之前做了一個用csv存取對話讀檔的系統,但是最近要用到大量的事件表

發現用csv會一大堆空格,不夠彈性,所以又跑回去以前不怎麼喜歡的xml格式

一開始想說xml好麻煩還要學,才跑去用csv比較直覺的

結果最近幾天看才發現,嗯?! 完全不會到入門其實蠻短的

保存用:
http://stanleyhlng.com/prettify-js/

https://rawgit.com/
========

<?xml version="1.0" encoding="utf-8"?>  
<DailyEvent>
    <Day id="1">
        <Event>
            event1
        </Event>
        <Dialog>
            "第一天"
        </Dialog>

    </Day>
    <Day id="2">
        <Event>
            event2
        </Event>
        <Dialog>
            "第二天"
        </Dialog>
    </Day>
</DailyEvent>

撰寫xml有幾個重點

1.宣告
<?xml version="1.0" encoding="utf-8"?>  
通常出現在XML文件的第一行,可寫可不寫
如果宣告了,version是必要寫上去的,然後後面的encoding則是選填
宣告了之後就可識別使用哪個編碼來代表文件中的字元了
像是
<?xml version="1.0" encoding="Shift-JIS"?>
就是使用日文編碼

2.先進後出
格式很像html那樣的寫法
基本上就是< >跟</ > 成雙成對出現
並且回文,意思就是先進後出,先寫的< >,最後再用</ >把它封起來
像上面的<DailyEvent> 一開始就寫了,如果裡面還要用別的<>就先擱著,如果沒有其他要寫的標籤,就可以封起來了
用文字表達就是 <1> <2> </2></1> 的感覺


3.樹狀結構
就跟樹一樣,只會有一個Root(父節點),指的就是上面範例的DailyEvent
不會有其他的Root了,然後再用這個Root去往下延伸
上面範例的第一個子節點是
<Day id="1">
同階層的另外一個子節點就是
<Day id="2">
而這兩個子節點又分別有兩個子節點

那資料就是可以儲存在某個節點的 <> 與 </> 中間那段空白,就像上面寫的第一天,第二天那樣

4.屬性
<>內可以填屬性,像是上面
<Day id="1">
內的 id="1",就是他的屬性,在unity內等等會用到


====

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Xml.Linq;
using System;
public class ReadXML : MonoBehaviour {
    public string id;
    public string eventContent;
    public string DialogContent;
    
    void Start () {

        var AllDays = XDocument.Load("Assets/DailyEvent_1.xml").Element("DailyEvent").Elements("Day");

        foreach (var day in AllDays)
        {
            id            = day.Attribute("id").Value.Trim();// 屬性
            eventContent  = day.Element("Event").Value.Trim();  // 內容                      
            DialogContent = day.Element("Dialog").Value.Trim(); //也是內容

            Debug.Log("day ID = " + id);
            Debug.Log("eventContent" + eventContent);
            Debug.Log("DialogContent" + DialogContent);
          
        }
    }
    
}

在Unity要讀取到xml檔案有兩種方法

一種是以前的XmlDocument
因為我用的不是這種的,所以這邊就先跳過了
有興趣的參考以下網頁

XML的簡單讀取與寫入

XML檔案基本操作-XmlDocument

第二種是比較新的XDocuments
可以用比較直覺地去讀取xml中的資料

要使用前先加入標頭檔
using System.Xml.Linq;

接下來就是開起xml檔了
先把輸入好的xml丟到unity內的Asset資料夾裡面,我是直接丟外面,當然也可以創建資料夾放到裡面,以下示範直接丟在外面的方式
XDocument AllDays = XDocument.Load("Assets/DailyEvent_1.xml");

那讀取完之後就是拿取裡面資料了
首先要先獲得它的節點
獲取節點有兩種方法
一種是你有很多個節點,使用的就是
根節點.Elements("XXXX");
另外一種就是只有單一節點
根節點.Element("XXXX");
基本上兩種方法就可以獲取到不同深度的節點了

拿取節點後要獲取內容的話就在後面.value就能拿到<與>之間的值了


拿取根節點的時候有比較步驟的方法,以下兩行都是相等的
 var AllDays = XDocument.Load("Assets/DailyEvent_1.xml").Element("DailyEvent");
 var AllDays = XDocument.Load("Assets/DailyEvent_1.xml").Root;

然後還有讀取節點的屬性
day.Attribute("id").Value

然後大致上就可以使用啦~ 還蠻直覺的
晚點放git



Share:
Read More

【C#】ref與out // 傳值與傳址

傳值Call by Value / 傳址 Call by Reference

學過c++的一定會遇到
傳值與傳址
一開始聽到整個
wtf 這兩個是尛阿

到最近看了一下ref跟out之後才真的了解
======

一般資料型別分為兩種
一個是實質型別
一個是參考型別

實質型別就是 int float char...等基礎的型別
而他變數記憶體存放的"內容"是值 所以稱為實"值"型別
也就是"傳值",當你在使用他的時候
他們之間傳遞的方式都是把值copy一份後再傳進去
像是以下
一開始宣告
int A=5, B=10;
並且設一個方法
void ChangeValue(int a,int b)
{
    a = 1;
    b = 2;
}

之後在Start()方法內調用
Debug.Log(" A  :" + A + " b :" + B);
 ChangeValue(A, B);
 Debug.Log(" A  :" + A + " b :" + B);
分別是將AB傳進去前跟傳進去後





可以看到傳進去後值都沒改變,這是因為使用的方式只是傳值(call by value)而已
意思就是把"值"複製給對方,而複製完改變的東西並不會影響到本身的值,因此不會做任何改變

而下面可以對照看看
 Car car11 = new Car("car11");
 Car car22 = new Car("car22");

    void ChangeNewCarValue(Car _car11, Car _car22)
    {
        _car11._carName = "ChangeCAR11";
        _car22._carName = "ChangeCAR22";

    }

同樣的宣告 同樣的方法 同樣在Start內打上
Debug.Log(" car11 :" + car11._carName + " car22 :" + car22._carName);
ChangeNewCarValue(car11, car22);
Debug.Log(" car11 :" + car11._carName + " car22 :" + car22._carName);
出來的結果則為






結果卻改變了,因此從上可以推論出來Car是一個傳址Call by Reference
意思就是,它傳遞的不是複製一份出來的值,而是傳遞丟入物件的記憶體位址
然後間接透過它來操作物件,跟指標很類似。

其實在C/C++的時候 正確是有三個名詞的
call by value 傳值、call by reference 傳參考、call by address傳址
但由於這裡要講的是C#,所以用官方的翻譯來敘述 ->詳細點我
如果要詳細了解這三個有什麼差別 可以再去google

ref、out

ref 關鍵字
會導致引數由參考加以傳遞,而非透過值。
參考程式碼 :
class RefExample
    {
        static void Method(ref int i)
        {
            // Rest the mouse pointer over i to verify that it is an int.
            // The following statement would cause a compiler error if i
            // were boxed as an object.
            i = i + 44;
        }

        static void Main()
        {
            int val = 1;
            Method(ref val);
            Console.WriteLine(val);

            // Output: 45
        }
    }


可以發現實質類型使用ref關鍵字之後,就會變得像是上面參考類型一樣
可以修改傳入的參數了
class RefExample
    {
        static void Method(ref int i)
        {
            // Rest the mouse pointer over i to verify that it is an int.
            // The following statement would cause a compiler error if i
            // were boxed as an object.
            i = i + 44;
        }

        static void Main()
        {
            int val = 1;
            Method(ref val);
            Console.WriteLine(val);

            // Output: 45
        }
    }

那問題來了,參考類型本身傳遞就可以直接修改值了
為何還會使用ref關鍵字加到參考型別身上呢?
1.明確提示
加了之後 不管給別人用還是自己用 都可以知道 傳入的參數是會被改變值得
不管傳入實質或參考都一樣
2.string的不變性
參考這裡
3. 為了修改默認值類型

ref重點:(msdn)
1.傳遞至 ref 參數的引數,在傳遞之前必須先初始化。
2.不能將ref和out用於async修飾詞定義的非同步方法。
3.有進有出

out關鍵字

基本上跟ref一樣
想要多個回傳值的時候,可以使用out

    class OutReturnExample
    {
        static void Method(out int i, out string s1, out string s2)
        {
            i = 44;
            s1 = "I've been returned";
            s2 = null;
        }
        static void Main()
        {
            int value;
            string str1, str2;
            Method(out value, out str1, out str2);
            // value is now 44
            // str1 is now "I've been returned"
            // str2 is (still) null;
        }
    }


ref跟out在使用上有很微小的差距

使用out的話,他不需要在被調用前初始化
但是調用者需要在返回之前指定輸出的參數

另一方面,可以用這樣去想
out類似於將方法附加返回值,也就是回傳多個值啦



Share:
Read More

【C#】特性

特性是什麼

簡單來說 
Unity最常看到的就是在屬性或字段前面加上
[Serializefield] private int Something = 5; 
而前面這個框框內的就是特性
它的功用就是賦予後面那一串陳述某種技能
像上面那個,就是Unity內的特性 
一般我們要在外面的editor調整數值,要將字段的層級調為pubic
但是有時候又不能讓他在其他腳本調用的時候被看見
這時候就可以用到它了→[Serializefield]  (點擊可看文件)
可以強制將私有字段設為在編輯器上可見






看起來就會變成這樣

然後還有,unity在更新它的api的時候 舊方法常常會被新方法取代
但一下把它移除,用戶難免會覺得很莫名 「常用的東西不見的 你在跟我開玩笑嘛!!」的感覺
於是他就使用了Obsolete這個特性,這個特性主要就是【宣告過期功能】
恩 , 超簡略 ,看起來就是這樣




其他還有很多各種不同的特性
這裡只是先簡短介紹一下 其他就慢慢去查唄
Share:
Read More

【演算法實作筆記】二分搜尋法 C#實作in Unity

用以搜尋已排序的一串資料,由小排到大

輸入:正整數n
輸出 :n在S中的位置

原理
輸入值與S陣列的中間值比大小
當輸入值比較大時,接下來只需要判斷S陣列中間值的右邊那一串陣列即可
反之亦然。


using UnityEngine;
using System.Collections;

public class BinarySearch_ : MonoBehaviour {

    public int middle;
    int[] hi = new int[5]{1,2,3,4,5};
    void Start()
    {
        middle = Location (hi, 0, 5, 3);
        binarysearch (hi, 2);
    }
    //遞迴版 二元搜尋
    //遞迴呼叫時如果不改變質卻傳進去會消耗很多變數的地址
    int Location(int[] data,int low , int high,int search)
    {

        int mid;

        if (low > high)
            return 0;
        else {
            mid = (low + high) / 2;

            if (search == data [mid])
                return mid;
            else if (search <= data [mid])
                return Location (data, low, mid - 1, search);
            else
                return Location (data, mid + 1, high,search);
                
        }

    }
    //普通版
    void binarysearch(int[] data,int search)
    {
        int low = 0;
        int high = data.Length;

        while (low <= high) {
            int mid = (low+high) / 2;
            if (data [mid] == search) {
                Debug.Log ("key" + mid);
                return;
            } else if (data [mid] > search) {
                high = mid - 1;
            } else if (data [mid] < search) {
                low = mid + 1;
            }
        }
    }
}

用UNITY實作,分遞迴跟普通版,多研究就能看出來了。
Share:
Read More

【Unity】使用動畫曲線 — AnimationCruve


有使用過Unity動畫狀態機的想必會覺得可以隨意新增Key來調整曲線這些功能很方便
那如果有天我只是想簡單做個事,像是把一張圖片放大,我個人會比較想能少一點東西就少一點東西,因此就可以使用到 AnimationCruve ,跟動畫機一樣可以調整曲線的類別。

關於AnimationCruve 在官方文檔中有詳細說明
https://docs.unity3d.com/ScriptReference/AnimationCurve.html

使用的時候就直接在腳本內宣告AnimationCruve

public AnimationCurve Curve;

在script外看來是這樣





夠簡單吧! 點開就能跟Animator一樣的使用了
點進去後可以操作keyframe,對某個keyframe點右鍵->editKey...可以設定他的值如下圖



















仔細看會看到上面的value跟time分別是旁邊的y軸跟x軸可以手動輸入比較精準

那要取出這些值呢,就是使用一個Evaluate方法(官方文檔),該方法就是丟入一個(time),他會返回一個(value)

那如果你要讓他像個動畫,想當然就是放在update裡面啦,不然你放在Start裡只會執行一次,也就是只拿到一個對應值而已
.
.
.
在這裡使用IEnumerator是因為我不想把放在Update裡面,然後又要每次停留1偵,不然while迴圈執行太快導致你看不清楚他有沒有變化

IEnumerator PlayAnimation()
    {

        float curveTime = 0f; 
        float curveAmount = Curve.Evaluate (curveTime);

        while (curveAmount<1.0f) {
        
            curveTime +=Time.deltaTime * Speed;
            curveAmount = Curve.Evaluate (curveTime);

            transform.localScale = new Vector3(curveAmount,curveAmount,curveAmount); //這裡我是把本身物件大小縮放

            yield return null;
        }
    }

先定義一個curveTime 將他當作曲線的time值(就上面講過的X軸的值)傳入
並且將curveTime隨時間增加,然後speed是我想比較方便控制他的速度才乘上去的
curveAmount = Curve.Evaluate (curveTime);這句就是把curveTime去查出對應的value是多少
之後就可以使用curveAmount來做動畫了,你可以改變物體大小...等很多事情
最後當然要等待下一偵啦,不然太快會看不到阿~

完整程式碼:

using UnityEngine;
using System.Collections;

public class WaveControl : MonoBehaviour {

    public AnimationCurve Curve;
    public float Speed;

    void Start () {
        StartCoroutine ("PlayAnimation");

    }

    IEnumerator PlayAnimation()
    {

        float curveTime = 0f;
        float curveAmount = Curve.Evaluate (curveTime);

        while (curveAmount<1.0f) {
        
            curveTime +=Time.deltaTime * Speed;
            curveAmount = Curve.Evaluate (curveTime);

            transform.localScale = new Vector3(curveAmount,curveAmount,curveAmount);

            yield return null;
        }
    }
}

====
16/10/5更:
忘記IEnumerator不能同時播放了XD
最後還是用回Update裡去了QQ
Share:
Read More

【UE4】Unreal 與HTC vive的結合 - 環境設置

題外話: 上次發布時間是5月27... 原本想說每個月發一篇的,但有時候做出的東西就真的很小很不足拿出來紀錄,而且有些也是自己隨便弄弄做出來的東西,半桶水而已也不好發XD
小弟玻璃心,如果說改正哪裡什麼的,哪邊錯誤的留言我會很開心,但如果出現:『像這種程度就自己紀錄就好別發出來的話』我的玻璃心會碎的QQ
不過最近因為實習,有研究unreal的引擎,想說可能有些人入門的時候會跟我一樣會遇到些困難,所以就還是PO了 XD,太深入的我也不太了解,我只能講出我所看到,所查到的各種問題,拜託鞭小力一點。
接下來也是一連串的Unreal,因為unity最近比較少碰XD

____________________


由於官方已經有怎樣設置環境的教學了,這邊只是將他補充說明與製作上會遇到的困難部分講解一下而已

官方也有個故障排除可以參考
點這裡

1. 要先把SteamVR套件下載下來 設置手上的htcVIVE

官方教學
因為htc vive硬體搭配的是SteamVR軟體
如果是什麼board之類的就是其他的 每款硬體都會搭配不等的軟體

在這步上會遇到的困難大概就是【頭戴顯示器】沒辦法搜尋到、【手把】無法搜尋、基地台((那兩顆正方形的))沒辦法偵測


【定位器】

線確定要連接好,記得頻道要設定,後面有顆按鈕可以按,一部設置成B,一部設置成C,然後設置成對角線((左上右下)),而且距離要在五公尺內


【頭戴顯示器】

定位器設定好後,如果偵測不到的話,你可以更新你的顯示卡驅動程式、重開機,記得頭戴顯示器要在你兩個基地台以內

【手把】

設定定位器後,長按電源鍵打開,建議一個一個打開,這部分比較沒什麼困難,當初也是一按就偵測到
--問題參考1


如果以上偵測不到,把SteamVR關掉,然後重開再試一次,大部分都是定位器有問題,因為那個頻道設置與偵測比較困難,參考以下





































2. UE4專案設置

官方教學

這部分相較比較簡單,比較要注意的是這個地方


看那個SteamVR那邊,預設是打勾的


















如果你打勾後,SteamVR開啟後也都連結了,還是灰色的,你就要把它取消打勾後重啟,在打勾一次重啟就會變可以使用了。

基本上只要設置Plugin就能完成與硬體的連接了,接下來就是連接手把、連接顯示器方面的事了~等下一篇唄

Share:
Read More

[C#] 使用Mathf.Sin與Cos取得圓上點座標


最近要使用到算圓,因此想到以前常用的三角函數,sin、cos



Mathf.sin 官方的api裡面註明了
Returns the sine of angle f in radians.
他輸入的是弧度,所以如果想求 圓上某個點的座標,要先把弧度轉換成角度

什麼是弧度呢?
看下圖應該很明顯了XD




(取自維基百科)


兩者關係就是

1弧度 = 360°/2π ≒ 57.29° 

1° = 2π/360° ≒ 0.0174533(弧度) 




這是比較公式化的,如果自己去算的話,就是照上面的圖,180°,分成180份

然後除以長度,就會得出0.017453....

這樣就知道1度等於0.0174533弧度,假如想求90度的話,就*90就好了

Mathf裡面已經定義好常數給你使用了

分別是
Mathf.Deg2Rad跟Mathf.Rad2Deg

以下簡單示範一下
float angleY = Mathf.Sin(60*Mathf.Deg2Rad);
float angleX = Mathf.Cos(60*Mathf.Deg2Rad);
Point1 = new Vector2(angleX, angleY);


Debug.DrawLine(Vector2.zero, Point1,Color.green);


結果: (( 其他線是測試用,上述代碼出現的是綠色那條))



而使用Sin可以使用拿來移動物體
使用上像是這樣

private Vector3 _startPosition;

    void Start()
    {
        _startPosition = transform.position;
    }

    void Update()
    {
        transform.position = _startPosition + new Vector3(Mathf.Sin(Time.time), 0.0f, 0.0f);
    }



這樣就會有平滑平滑的感覺啦~
Share:
Read More

【UGUI】不規則圖片觸發範圍修改

NGUI有boxcollider可以自己調整觸發的範圍
但UGUI由於不是用boxcollider來觸發的,所以要修改也要有另外個方法

基本上用雨松的方法就行了-->連結在此

但找到另外一種方法,可以少寫比較多的代碼,但比較不靈活(?,沒辦法自己控制想要的範圍

首先有這麼一張圖,做成UGUI的按鈕的話,透明的地方也會被觸發到

而今天我想消除透明的地方,只有有顏色的地方才能觸發


先把匯入的圖檔先調一下,調成可讀可寫的


然後+入一個腳本
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class UGUI_Button_alpha : MonoBehaviour {

    public Image image;
    public float threshold = 0.5f;
    
    void Start () {
        image.eventAlphaThreshold = threshold;
    }
    
}

原理其實Unity API裡面寫得很清楚了

讀取Image的eventAlphaThreshold值,來判斷圖片的Alpha值(所以要把圖片設定為可讀可寫)

1的話就是總是會通過,調低就會忽略透明度,所以到最後點擊圖片才會響應。

Image就放你想套用的那張圖片,然後再調一下threshold 到你滿意的值就好

Share:
Read More