【演算法實作筆記】二分搜尋法 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

[Unity] NGUI與UGUI分別如何攔截事件


由於常常會發生點擊了介面,遊戲內的物件也會被觸發的關係
所以會用到攔截事件,而NGUI的方面比較簡單,只要添加

if (UICamera.isOverUI)
    return;

當我們在射線檢測的時候,如果點擊到UI就不會發生反應了


UGUI方面的話則是

#if IPHONE || ANDROID
            if (EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId))
            return;
#else
            if (EventSystem.current.IsPointerOverGameObject())
                return;
#endif

由於要判斷平台,所以比較長
下面那句則是PC使用的
Share:
Read More

【C#】continue跟return與break用法

很多書都有提到,但最近寫的專題裡面用到就順便記下來了


continue :

跳過這次迴圈(i),並執行下一次(i+1)的迴圈
然後執行完迴圈後會回到上一層繼續執行未完成部分
Ex:
void Start () {




for (int j=0; j<5; j++) {
  

   if(j==3)
    continue;
   Debug.Log("continue: "+j);
  }

  Debug.Log ("我在外面");

 }


假設今天有個for循環 印出0~4數字
這時候如果我們想說,不印出3
這時候只要像上面那樣
就可以略過3了


並且,他會繼續執行略過後的方法


return :
回傳、中斷

一碰到return ,"函數" 就終止然後return 值後(也可以直接return),直接結束目前函式,不會繼續執行迴圈外的程式
void Start () {

Debug.Log ("進入Start");

TestReturn ();

Debug.Log ("我在Start外面");

}


void TestReturn()
{
for(int i=0;i<5;i++)
  {
   if(i==2)
    return;
   Debug.Log("Test Return:"+i);
  }

  Debug.Log ("in testReturn");
 }



看看TestReturn函式,return的話,會直接跳出目前的函式,不會繼續執行迴圈內外的函式,然後回到上一層繼續執行。



break :
直接跳出迴圈後,會繼續執行迴圈外的程式

void Start () {

Debug.Log ("進入Start");

TestBreak ();

Debug.Log ("我在Start外面");

}


void TestBreak()
{
for(int i=0;i<5;i++)
  {
   if(i==2)
    break;
   Debug.Log("Test break:"+i);
  }

  Debug.Log ("in break");
 }









跟上面差別就是 會執行迴圈後的程式
Share:
Read More