unity3d5.1物體橢圓旋轉選擇界面實現(二)

       在上一篇實現了橢圓的方塊擺佈之後,接着實現方塊選擇時候的移動效果,由於最近比較忙,忘了寫後續了。而且自己正好加到項目中去了,爲了適應項目改了很多實現方式,可能會稍有出入,只好以最終版爲準了。

       我在unity中並沒有找到直接將某對象移動到另一位置的api,因此,要實現移動效果,方式有三種:

       1、使用Itween插件提供的MoveTo函數,能夠達到移動效果。但是考慮情況比較複雜,首先必須方塊數目大於3,移動效果可能好一點,並且往某個方向移動時,最後一個是平整的過去的,顯得怪異。同時方塊爲2時,一前一後移動特別怪異,從上往下和從下往上,這兩點比較難解決;

       2、使用Itween插件的自動尋路算法,看了下,貌似是設置幾個點,然後讓方塊按照先後順序移動到終點就行了,這樣的話,可以將每個方塊的軌跡取出幾個點,傳入,然後ok;

       3、也僅僅是模擬,所以我在這裏去三段式,自己寫一個類似Itween的方法,同時自定義,取路徑上的三個點(包括終點),每個點傳入後,將遞歸執行移動到目標點,達到近視橢圓軌跡的效果,理論上來說,點越多,橢圓軌跡越清晰,但是感覺三段式就夠用了,所以自己寫了個。

        第一種和第三種方法是實踐了的,第二種方法暫時沒去實驗,但是感覺難度不大,方法都有了,實現也不會費勁。第一種太過簡單就不贅述了,取出終點和起點就行了,同時不完美。


1.實現左右變換位置

      先實現點擊左右按鈕後,幾個方塊會變換好位置,且變換的位置是準確的。

定義一個方向枚舉,用以判斷當前操作是向左還是向右操作

public enum MYDirection
{
    //向左
    LEFT,
    //向右
    RIGHT
}

然後給左右按鈕分別綁定左右按鈕的回調函數,在界面裏添加onclick事件即可

<pre name="code" class="csharp">  //往左滑動的回調函數即整體往左移動
    public void LeftButtonEvent()
    {
        //添加到容器裏,用以多次點擊時延遲執行
        m_eventList.Add(MYDirection.LEFT);//該容器要去聲明,防止多次快速點擊時亂掉,保存每個點擊事件,一一遞歸執行
        doEvent();
    }
    //往右滑動的回調函數
    public void RightButtonEvent()
    {
        //添加到容器裏,用以多次點擊時延遲執行
        m_eventList.Add(MYDirection.RIGHT);//該容器要去聲明,防止多次快速點擊時亂掉,保存每個點擊事件,一一遞歸執行
        doEvent();
    }
    //集中判斷執行哪個按鈕的回調函數
    public void doEvent()
    {
        if(isruningone==true)//如果已經在執行着一個了,那麼就不再執行,該變量也需聲明,保證每次執行是第一個,暫時用不到
        {
            return;
        }
        //如果所有的都執行完了,那麼跳出
        if(m_eventList.Count<=0)
        {
            return;
        }
        isruningone = true;//設置爲true,鎖定,防止多次執行
        //如果沒有,那麼取出一個來執行
        MYButtonEvent(m_eventList[0]);
        m_eventList.RemoveAt(0);
    }
 //根據方向來不斷執行移動
    void  MYButtonEvent(MYDirection _direction)
    {
        //往左移動
       if(_direction==MYDirection.LEFT)
       {
           GameObject temp0 = Sprites[0];//先保存第一個的引用
           if (size <= 0)
           {
               return;
           }
           //右邊全部往前一格
           for (int i = 0; i < size - 1; i++)
           {
               Sprites[i] = Sprites[i + 1];
           }
           //右邊最後一個直接賦值
           Sprites[size - 1] = Sprites[Sprites.Length - 1];
           //左邊全部往後一格
           for (int i = Sprites.Length - 1; i > size; i--)
           {
               Sprites[i] = Sprites[i - 1];
           }
           //左邊第一個直接賦值
           Sprites[size] = temp0;

           //移動方塊
           Move(MYDirection.LEFT);
           return;
       }
           //往右移動
       else
       {
           GameObject temp0 = Sprites[size];//先保存左邊第一個的引用
           if (size <= 0)
           {
               return;
           }
           //左邊全部往前一格
           for (int i = size; i < Sprites.Length - 1; i++)
           {
               Sprites[i] = Sprites[i + 1];
           }
           //左邊最後一個直接賦值
           Sprites[Sprites.Length - 1] = Sprites[size - 1];
           //右邊全部往後一格
           for (int i = size - 1; i > 0; i--)
           {
               Sprites[i] = Sprites[i - 1];
           }
           //左邊第一個直接賦值
           Sprites[0] = temp0;
           //左邊全部往後一格
           //移動方塊
           Move(MYDirection.RIGHT);
           return;
       }
    }




Move操作,即每次給它重設座標即可,因爲暫時不加移動效果

<pre name="code" class="csharp"> 
//移動的函數
    void Move(MYDirection _direction)
    {

        int size = Sprites.Length;
        for (int i = 0; i < size; i++)
        {
            Sprites[i].transform.position=location[i];
        }
      ResetDeep();
           isruningone = false;
            i_havemovesprite = 0;
            doEvent();
    }
void ResetDeep()
    {
        int dep = 0;
        //右半邊
        for (int i =size-1; i>=0; i--)
        {
            Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
            dep++;
        }
        dep = 0;
        //左半邊
        for (int i = Sprites.Length - 1; i >=size; i--)
        {
            Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
            dep++;
        }
    }

至此,應該來說可以實現點擊變換位置了,雖然沒有移動效果(我是按照寫好了的版本去寫前面的,可能會有錯誤,大致思想在這兒,變量問題可以自己添加)。


2.創建自己的Move函數腳本

如下:

using UnityEngine;
using System.Collections;
using System;
using System.Reflection;
using UnityEditor;
using System.Collections.Generic;
public class ManagerEffective : MonoBehaviour
{
    public enum LoopType//循環方式
    {
        one,//一次
        loop,//循環
        pingpong//來回
    }
    public static ArrayList ef_tive = new ArrayList();
    //橢圓測試
    bool m_isEllips=false;
     List<Vector3> TargetPos=new List<Vector3>();
    float nowtimelimit;
    int count = 0;

    //多少秒內完成,開始前等待時間
    public float time, delay;
    //循環方式
    public LoopType loopType;
    
    public bool isRunning;//判斷是否在更新位置




    //代理函數
    private delegate void ApplyMthood();
    private ApplyMthood apply;//代理函數對象
    private Vector3[] vector3s;//用以保存當前的進度,目標的位置信息等
    //當前時間,進度
    private float runningTime, percentage;
    private float lastRealTime; // Added by PressPlay
    private bool useRealTime; // Added by PressPlay
    private Hashtable myhashtable;//當前的hashtable
    private string Actiontype;//動作類型

    public static class Defaults//默認值
    {
        public static float time = 0.5f;//默認移動時間
        public static float delaytime = 0;
        public static LoopType loopType = LoopType.one;
        public static string Actiontype = "MoveTo";
    }
    //直接外調的函數,直接移動
    public static void MoveTo(GameObject _object,Vector3 position,float time)
    {
        MoveTo(_object,Hash("position",position,"time",time));
    }
    //通過哈希表來移動的函數,直接移動
    public static void MoveTo(GameObject _object,Hashtable args)
    {
        args = CleanArgs(args);
        if (args.Contains("position"))
        {
            if (args["position"].GetType() == typeof(Transform))
            {
                Transform transform = (Transform)args["position"];
                args["position"] = new Vector3(transform.position.x, transform.position.y, transform.position.z);
                args["rotation"] = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
                args["scale"] = new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
            }
        }
        args.Add("ActionType","MoveTo");
        Lunch(_object,args);
    }
    //橢圓移動效果
    public static void MoveTo(GameObject _object, Vector3 position, float time, List<Vector3> _date)
    {
        
        MoveTo(_object, Hash("position", position, "time", time),_date);
    }
    //通過哈希表來移動的函數,橢圓移動效果
    public static void MoveTo(GameObject _object, Hashtable args, List<Vector3> _date)
    {
        args = CleanArgs(args);
        if (args.Contains("position"))
        {
            if (args["position"].GetType() == typeof(Transform))
            {
                Transform transform = (Transform)args["position"];
                args["position"] = new Vector3(transform.position.x, transform.position.y, transform.position.z);
                args["rotation"] = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y, transform.eulerAngles.z);
                args["scale"] = new Vector3(transform.localScale.x, transform.localScale.y, transform.localScale.z);
            }
        }
        args.Add("ActionType", "MoveTo");
        Lunch(_object, args);
    }
    public static void Lunch(GameObject _object, Hashtable args)
    {
        if (!args.Contains("target"))
        {
            args["target"] = _object;
        }
        ef_tive.Insert(0,args);
        _object.AddComponent<ManagerEffective>();
    }
    //根據數組轉換成一個哈希表
    public static Hashtable Hash(params object[] args)
    {
        Hashtable hashTable = new Hashtable(args.Length / 2);
        if (args.Length % 2 != 0)
        {
            Debug.LogError("Tween Error: Hash requires an even number of arguments!");
            return null;
        }
        else
        {
            int i = 0;
            while (i < args.Length - 1)
            {
                hashTable.Add(args[i], args[i + 1]);
                i += 2;
            }
            return hashTable;
        }
    }
    //保證都是float類型的
    //cast any accidentally supplied doubles and ints as floats as iTween only uses floats internally and unify parameter case:
    static Hashtable CleanArgs(Hashtable args)
    {
        Hashtable argsCopy = new Hashtable(args.Count);
        Hashtable argsCaseUnified = new Hashtable(args.Count);

        foreach (DictionaryEntry item in args)
        {
            argsCopy.Add(item.Key, item.Value);
        }

        foreach (DictionaryEntry item in argsCopy)
        {
            if (item.Value.GetType() == typeof(System.Int32))
            {
                int original = (int)item.Value;
                float casted = (float)original;
                args[item.Key] = casted;
            }
            if (item.Value.GetType() == typeof(System.Double))
            {
                double original = (double)item.Value;
                float casted = (float)original;
                args[item.Key] = casted;
            }
        }

        //unify parameter case:
        foreach (DictionaryEntry item in args)
        {
            argsCaseUnified.Add(item.Key.ToString().ToLower(), item.Value);
        }

        //swap back case unification:
        args = argsCaseUnified;
        return args;
    }
    void Awake()
    {
        
        RetrieveArgs();//初始化哈希表中移動參數
        lastRealTime = Time.realtimeSinceStartup; // Added by PressPlay
    }
    
    // Use this for initialization
    void  Start()
    {
        ConflictCheck();
        if(m_isEllips==true){
            StartCoroutine( EllipseDelay());
            return;
        }
        StartCoroutine(EFDelay());
	}
    // Update is called once per frame
    void Update()
    {
        if (isRunning)
        {
            if(m_isEllips)
            {
                if (percentage < 1f)
                {
                    EllipseUpdate();
                }
                else
                {
                    EllipseComplete();
                }
            }
            else
            {
                if (percentage < 1f)
                {
                    actionUpdate();
                }
                else
                {
                    actionComplete();
                }
            }
           
        }
    }
    //橢圓部分
    IEnumerator EllipseDelay()
    {    //間隔delaytime之後開始執行
        yield return new WaitForSeconds(delay);
        //根據類型設置代理函數
        switch (Actiontype)
        {
            case "MoveTo":
                EllipseGenerateMoveToTargets();
                apply = new ApplyMthood(EllipseApplyMoveToTargets);
                break;
            case "ScaleTo":
                break;
        }
        //初始化必要數據
        EllipseActionStart();
    }
    void EllipseActionStart()
    {
        isRunning = true;//開始運動了
       
    }
    void EllipseGenerateMoveToTargets()
    {
        Vector3 endlPos=new Vector3();
             if (myhashtable.Contains("position"))
        {
            if (myhashtable["position"].GetType() == typeof(Transform))
            {
                Transform trans = (Transform)myhashtable["position"];
                endlPos = trans.position;
            }
            else if (myhashtable["position"].GetType() == typeof(Vector3))
            {
                endlPos = (Vector3)myhashtable["position"];
            }
            else
            {//第三種方式,直接輸入xyz表達目的值     
                if (myhashtable.Contains("x"))
                {
                    endlPos.x = (float)myhashtable["x"];
                }
                if (myhashtable.Contains("y"))
                {
                   endlPos.y = (float)myhashtable["y"];
                }
                if (myhashtable.Contains("z"))
                {
                    endlPos.z = (float)myhashtable["z"];
                }
            }
        }
        /*int endAngle = getAngle(endlPos);
        int StartAngle = getAngle(transform.position);
       int  loacleangle=0;
        if(ef_date._direction==MYDirection.LEFT){
            if(endAngle>270 && StartAngle<90)
            {
            loacleangle=-(360-endAngle+StartAngle)/3;
             }
            else{
                loacleangle=(endAngle-StartAngle)/3;
            }
        }
        else{
              loacleangle=(endAngle-StartAngle)/3;
        }
        float  angle=(float)(StartAngle+loacleangle);
        Vector3 centPos=ef_date.centPos;
        Vector3 tem = getPosition(angle, centPos);
        TargetPos.Add(tem);
        angle+=loacleangle;
        tem =getPosition(angle, centPos);
        TargetPos.Add(tem);
         TargetPos.Add(endlPos);*/
      
        //values holder [0] from, [1] to, [2] calculated value from ease equation:
        vector3s = new Vector3[3];//即第一個是出發點,第二個是目標點,第三個時當前點
        vector3s[0] = transform.position; ;
       vector3s[1] =TargetPos[0];
       float itim = (1.0f/(float)TargetPos.Count);
       nowtimelimit =  itim* time;
       TargetPos.RemoveAt(0);
    }
    void EllipseApplyMoveToTargets()
    {
        //calculate:
        vector3s[2].x = linear(vector3s[0].x, vector3s[1].x, percentage);
        vector3s[2].y = linear(vector3s[0].y, vector3s[1].y, percentage);
        vector3s[2].z = linear(vector3s[0].z, vector3s[1].z, percentage);

        transform.position = vector3s[2];
        //dial in:
        if (percentage == 1)
        {
            transform.position = vector3s[1];
        }
    }
    //移動的update
    void EllipseUpdate()
    {
        apply();
        runningTime += Time.deltaTime;
        percentage = runningTime / nowtimelimit;
    }
    //重新來一個移動
    void ResetEllipseMove()
    {
        vector3s[0] = transform.position; ;
        vector3s[1] = TargetPos[0];
      // nowtimelimit = (1 / TargetPos.Count) * time;
        TargetPos.RemoveAt(0);
    }

   
    //移動到當前位置後,判斷是否完成所有移動
    void EllipseComplete()
    {
        isRunning = false;
        percentage =1;
        apply();

        if(TargetPos.Count==0)
        {
            Dispose();
            CallBack("oncomplete");
        }
        else
        {
            percentage = 0;
            runningTime = 0;
            ResetEllipseMove();
            EllipseActionStart();
        }
        
    }



    //
    #region #1 Normal
    void ConflictCheck()
    {//if a new iTween is about to run and is of the same type as an in progress iTween this will destroy the previous if the new one is NOT identical in every way or it will destroy the new iTween if they are:	
        Component[] tweens = GetComponents(typeof(ManagerEffective));
        foreach (ManagerEffective item in tweens)
        {
            if (item.Actiontype == "value")
            {
                return;
            }
            else if (item.isRunning && item.Actiontype == Actiontype)
            {
               
                //step 1: check for length first since it's the fastest:
                if (item.myhashtable.Count != myhashtable.Count)
                {
                    item.Dispose();
                    return;
                }
                //step 2: side-by-side check to figure out if this is an identical tween scenario to handle Update usages of iTween:
                foreach (DictionaryEntry currentProp in myhashtable)
                {
                    if (!item.myhashtable.Contains(currentProp.Key))
                    {
                        item.Dispose();
                        return;
                    }
                    else
                    {
                        if (!item.myhashtable[currentProp.Key].Equals(myhashtable[currentProp.Key]))
                        {//if we aren't comparing ids and something isn't exactly the same replace the running iTween: 
                            item.Dispose();
                            return;
                        }
                    }
                }

                //step 3: prevent a new iTween addition if it is identical to the currently running iTween
                Dispose();
                //Destroy(this);	
            }
        }
    }

    IEnumerator EFDelay()
    {//間隔delaytime之後開始執行
        yield return new WaitForSeconds(delay);
        //初始化必要數據
        ActionStart();
    }
    void ActionStart()
    {
        isRunning = true;//開始運動了
        StartInit();
    }
    void StartInit()
    {//根據類型設置代理函數
        switch(Actiontype){
            case "MoveTo":
                GenerateMoveToTargets();
                apply = new ApplyMthood(ApplyMoveToTargets);
                break;
            case "ScaleTo":
                break;
        }
    }
    void GenerateMoveToTargets()
    {
        //values holder [0] from, [1] to, [2] calculated value from ease equation:
        vector3s = new Vector3[3];//即第一個是出發點,第二個是目標點,第三個時當前點
        vector3s[0] = vector3s[1] = transform.position;
        if(myhashtable.Contains("position")){
            if (myhashtable["position"].GetType() == typeof(Transform))
            {
                Transform trans = (Transform)myhashtable["position"];
                vector3s[1] = trans.position;
            }
            else if (myhashtable["position"].GetType() == typeof(Vector3))
            {
                vector3s[1] = (Vector3)myhashtable["position"];
            }
            else
            {//第三種方式,直接輸入xyz表達目的值     
                if(myhashtable.Contains("x")){
                    vector3s[1].x=(float)myhashtable["x"];
                }
                if (myhashtable.Contains("y"))
                {
                    vector3s[1].x = (float)myhashtable["y"];
                }
                if (myhashtable.Contains("z"))
                {
                    vector3s[1].x = (float)myhashtable["z"];
                }
            }
        }
    }
    void ApplyMoveToTargets()
    {
        //calculate:
        vector3s[2].x = linear(vector3s[0].x, vector3s[1].x, percentage);
        vector3s[2].y = linear(vector3s[0].y, vector3s[1].y, percentage);
        vector3s[2].z = linear(vector3s[0].z, vector3s[1].z, percentage);

        transform.position = vector3s[2];
        //dial in:
        if (percentage == 1)
        {
            transform.position = vector3s[1];
        }
    }
    //獲取當前的目標位置
    private float linear(float start, float end, float value)
    {
        return Mathf.Lerp(start, end, value);
    }
	
    
    //動作update
    void actionUpdate()
    {
        apply();
        UpdatePercentage();
    }
   void  UpdatePercentage()
   {
     
           runningTime += Time.deltaTime;
           percentage =runningTime /time;
   }
    //動作完成
    void actionComplete()
    {
        isRunning = false;
        percentage = 1;
        apply();

        Dispose();
        CallBack("oncomplete");
    }
    //消除腳本
    void Dispose()
    {
        for (int i = 0; i < ef_tive.Count; i++)
        {
            Hashtable tweenEntry = (Hashtable)ef_tive[i];
            if (tweenEntry ==myhashtable)
            {
                ef_tive.Remove(tweenEntry);
                break;
            }
        }
        Destroy(this);
    }	
    //初始化哈希表所有需要的信息
    void RetrieveArgs()
    {
         
        foreach (Hashtable item in ef_tive)
        {
            if ((GameObject)item["target"] == gameObject)
            {
                myhashtable = item;
                break;
            }
        }

        if (myhashtable.Contains("time"))
        {
            time = (float)myhashtable["time"];
        }
        else
        {
            time = Defaults.time;
        }
        if (myhashtable.Contains("delay"))
        {
            delay = (float)myhashtable["delay"];
        }
        else
        {
            delay = Defaults.delaytime;
        }

        if (myhashtable.Contains("looptype"))
        {
            //allows loopType to be set as either an enum(C# friendly) or a string(JS friendly), string case usage doesn't matter to further increase usability:
            if (myhashtable["looptype"].GetType() == typeof(LoopType))
            {
                loopType = (LoopType)myhashtable["looptype"];
            }
            else
            {
                try
                {
                    loopType = (LoopType)Enum.Parse(typeof(LoopType), (string)myhashtable["looptype"], true);
                }
                catch
                {
                    Debug.LogWarning("iTween: Unsupported loopType supplied! Default will be used.");
                    loopType = ManagerEffective.LoopType.one;
                }
            }
        }
        else
        {
            loopType = ManagerEffective.LoopType.one;
        }
        if (myhashtable.Contains("ActionType"))
        {
            Actiontype = (string)myhashtable["ActionType"];
        }
        else
        {
            Actiontype = Defaults.Actiontype;
        }
        if (myhashtable.Contains("ellipse"))
        {
            m_isEllips = true;
            TargetPos = (List<Vector3>)myhashtable["ellipse"];
        }
        
    }
    //當運動完之後的回調函數
    void CallBack(string callbackType)
    {
        if (myhashtable.Contains(callbackType) && !myhashtable.Contains("ischild"))
        {
            //establish target:
            GameObject target;
            if (myhashtable.Contains(callbackType + "target"))
            {
                target = (GameObject)myhashtable[callbackType + "target"];
            }
            else
            {
                target = gameObject;
            }

            //throw an error if a string wasn't passed for callback:
            if (myhashtable[callbackType].GetType() == typeof(System.String))
            {
                target.SendMessage((string)myhashtable[callbackType], (object)myhashtable[callbackType + "params"], SendMessageOptions.DontRequireReceiver);
            }
            else
            {
                Debug.LogError("iTween Error: Callback method references must be passed as a String!");
                // Destroy(this);
            }
        }
    }
    #endregion
}
因爲是拓展版本,一開始我只是仿照寫了一個MoveTo函數機制,後來再拓展的橢圓機制,所以保留兩者吧,既可以直線移動,多一個參數作爲橢圓移動,_date參數沒有用到,只是懶得刪除,並且反正作爲標識吧,用法與Itween相同,只需要拖Ellipse腳本就行了,ManagerEffective只是個方法腳本,不用添加。


3.實現橢圓運動軌跡

因爲上的是最終版本,所以很多參數變了,用法變了,第一篇只能當做是思路提供了,在我這裏方塊改成了Button,所以Button保持了最前面的是可以點擊的,其他的不能點擊,並且參數改了,button是自己新建一個button當做prefab,然後把button刪除,當做參數對象傳給腳本,所以場景是沒有button存在的:


這是未運行的場景,只有左右按鈕↑

這個是canvas的參數,也就是Ellipse的參數,第一個是你要創建的方塊(button)對象,第二個是中心點,第三個時數目,第四個是角度偏移↑

這個是button對象↑

運行圖片:


代碼如下:

<pre name="code" class="csharp">using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using UnityEngine.UI;
public enum MYDirection
{
    //向左
    LEFT,
    //向右
    RIGHT
}

public class Ellipse : MonoBehaviour 
{
    //Test 自定義
    public GameObject whichshouldmake;
    public Vector3 Point;
    public int num;

    //保存需要排序的精靈容器
    private GameObject[] Sprites;
  //  private Transform centerPoint;//橢圓的中心點
    public float anglecheap = 25;//每個方塊間的角度偏移
    //保存位置點
    private List<Vector3> location = new List<Vector3>();

    
    private float angle =270;//第一個保證是中心位置的,當前到的角度
    private float firstangle = 270;//記錄第一個角度,用以左右對稱
    private float r =90;
    private float R = 150;

    int size = 0;//即對象數組的一半,奇數爲總長度+1/2,偶數爲一半
    int depcount = 0;//用以判斷是否需要更新渲染層級
    //用以判斷當前是否所有的按鈕回調都執行完了
    List<MYDirection> m_eventList = new List<MYDirection>();
    bool isruningone = false;//是否已經在執行一個移動回調了。
    int i_havemovesprite = 0;//計數用,如果已經移動完所有的方塊,那麼可以運行下一個按鈕回調了
    private Vector3 centerPos = new Vector3();
    void Awake()
    {
        Sprites=new GameObject[num];
        //獲取當前示例按鈕的大小,用以保證做出來的按鈕大小是一樣的
        Rect size = whichshouldmake.GetComponent<RectTransform>().rect;
        //保證被克隆出來的一樣
        Vector2 anchorMax = new Vector2(size.width/Screen.width,size.height/Screen.height);

        centerPos = Point;
        for (int i = 0; i < num;i++ )
        {
            GameObject _objcet;
           _objcet= Instantiate(whichshouldmake,Point,whichshouldmake.transform.rotation)as GameObject;
           _objcet.transform.parent = gameObject.transform;
           var rcTrans = _objcet.GetComponent<RectTransform>();
           // 錨點上下貼邊
          // rcTrans.localScale = new Vector3(1, 1, 1);
        //   rcTrans.anchorMin = centerPos;
          // rcTrans.anchorMax = new Vector2(centerPos.x + 0.1f, centerPos.y + 0.2f);
           rcTrans.localScale = new Vector3(1, 1, 1);
           rcTrans.anchorMin = new Vector2(0, 0);
           rcTrans.anchorMax = anchorMax;
           // 佔滿整個錨點區域
           rcTrans.offsetMin = rcTrans.offsetMax = new Vector2(0, 0);
           Sprites[i] = _objcet;
        }
       
    }
	// Use this for initialization
	void Start () 
    {
        if (Sprites.Length % 2 == 0)
        {
            size = Sprites.Length / 2;
        }
        else
        {
            size = (Sprites.Length + 1) / 2;
        }
        //排序分級顯示
        makespriteSort();
        //重置渲染層級
        ResetDeep();
	}
    //給這些精靈排序顯示
    void makespriteSort()
    {
        //取出橢圓的中心點
     //   Vector3 center = centerPoint.position;
       // centerPos = center;
        //判斷該數組的個數奇偶性,如果是偶數,那麼需要留出一個來放到對面
        if (Sprites.Length % 2 == 0)
        {
            //右半邊
            for (int i = 0; i < size; i++)
            {
                Sprites[i].transform.position = getPosition(angle, centerPos);
         //       m_rightsprite.Add(Sprites[i]);
                angle += anglecheap;
            }
            //第一個已經得是左邊了
            angle = firstangle - anglecheap;
            //左半邊
            for (int i = size; i < Sprites.Length-1; i++)
            {
                Sprites[i].transform.position = getPosition(angle, centerPos);
                angle -= anglecheap;
              //  m_leftsprite.Add(Sprites[i]);
            }
            //最後一個
            Sprites[Sprites.Length - 1].transform.position = getPosition(90, centerPos);
           // m_leftsprite.Add(Sprites[Sprites.Length - 1]);
            return;
        }
        //如果不是偶數,那麼出去中間那個,正好正常顯示
        else
        {
            //右半邊
            for (int i = 0;i<size; i++)
            {
                Sprites[i].transform.position = getPosition(angle, centerPos);
            //    m_rightsprite.Add(Sprites[i]);
                angle += anglecheap;
            }
            //第一個已經得是左邊了
            angle = firstangle - anglecheap;
            //左半邊
            for (int i = size;i < Sprites.Length; i++)
            {
                Sprites[i].transform.position = getPosition(angle, centerPos);
              //  m_leftsprite.Add(Sprites[i]);
                angle -= anglecheap;
            }
            return;
        }
       
    }
    //獲取當前角度的座標
    Vector3 getPosition(float _angle,Vector3 _centerposition)
    {
        float hudu = (_angle/180f) * Mathf.PI;
        float cosx = Mathf.Cos(hudu);
        float sinx = Mathf.Sin(hudu);
        float x = _centerposition.x + R * cosx;
        float y = _centerposition.y + r * sinx;
        Vector3 point = new Vector3(x, y, 0);
        //添加到容器保存
       location.Add(point);
        return  point;
    }
    //根據當前左邊判斷角度
    int getAngle(Vector3 _point, Vector3 _centerposition)
    {
        int _angle = 0;
        float hudu = (_angle / 180f) * Mathf.PI;
        float cosx = Mathf.Cos(hudu);
        float sinx = Mathf.Sin(hudu);
        float x = _centerposition.x + R * cosx;
        float y = _centerposition.y + r * sinx;
        Vector3 point = new Vector3(x, y, 0);
        //添加到容器保存
        location.Add(point);
        return _angle;
    }
    //根據當前左右容器調整所有控件的渲染層級
    void ResetDeep()
    {
        int dep = 0;
        //右半邊
        for (int i =size-1; i>=0; i--)
        {
            if(i!=0)
            {
                Sprites[i].GetComponent<Button>().enabled = false;
            }
            else
            {
                Sprites[i].GetComponent<Button>().enabled = true;
            }
            Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
            dep++;
        }
        dep = 0;
        //左半邊
        for (int i = Sprites.Length - 1; i >=size; i--)
        {
            Sprites[i].GetComponent<Button>().enabled = false;
            Sprites[i].GetComponent<Transform>().SetSiblingIndex(dep);
            dep++;
        }
    }
    //根據方向來不斷執行移動
    void  MYButtonEvent(MYDirection _direction)
    {
        //往左移動
       if(_direction==MYDirection.LEFT)
       {
           GameObject temp0 = Sprites[0];//先保存第一個的引用
           if (size <= 0)
           {
               return;
           }
           //右邊全部往前一格
           for (int i = 0; i < size - 1; i++)
           {
               Sprites[i] = Sprites[i + 1];
           }
           //右邊最後一個直接賦值
           Sprites[size - 1] = Sprites[Sprites.Length - 1];
           //左邊全部往後一格
           for (int i = Sprites.Length - 1; i > size; i--)
           {
               Sprites[i] = Sprites[i - 1];
           }
           //左邊第一個直接賦值
           Sprites[size] = temp0;

           //移動方塊
           Move(MYDirection.LEFT);
           return;
       }
           //往右移動
       else
       {
           GameObject temp0 = Sprites[size];//先保存左邊第一個的引用
           if (size <= 0)
           {
               return;
           }
           //左邊全部往前一格
           for (int i = size; i < Sprites.Length - 1; i++)
           {
               Sprites[i] = Sprites[i + 1];
           }
           //左邊最後一個直接賦值
           Sprites[Sprites.Length - 1] = Sprites[size - 1];
           //右邊全部往後一格
           for (int i = size - 1; i > 0; i--)
           {
               Sprites[i] = Sprites[i - 1];
           }
           //左邊第一個直接賦值
           Sprites[0] = temp0;
           //左邊全部往後一格
           //移動方塊
           Move(MYDirection.RIGHT);
           return;
       }
    }
    
    //往左滑動的回調函數即整體往左移動
    public void LeftButtonEvent()
    {
        //添加到容器裏,用以多次點擊時延遲執行
        m_eventList.Add(MYDirection.LEFT);
        doEvent();
    }
    //往右滑動的回調函數
    public void RightButtonEvent()
    {
        //添加到容器裏,用以多次點擊時延遲執行
        m_eventList.Add(MYDirection.RIGHT);
        doEvent();
    }
    //集中判斷執行哪個按鈕的回調函數
    public void doEvent()
    {
        if(isruningone==true)//如果已經在執行着一個了,那麼就不再執行
        {
            return;
        }
        //如果所有的都執行完了,那麼跳出
        if(m_eventList.Count<=0)
        {
            return;
        }
        isruningone = true;//設置爲true,鎖定,防止多次執行
        //如果沒有,那麼取出一個來執行
        MYButtonEvent(m_eventList[0]);
        m_eventList.RemoveAt(0);
    }
    //移動的函數
    void Move(MYDirection _direction)
    {

        int size = Sprites.Length;
        for (int i = 0; i < size; i++)
        {
            //使用itween接口實現移動效果
            Hashtable table = gethashtable(location[i]);
           // iTween.MoveTo(Sprites[i],table);
            List<Vector3> newlist = getListend(Sprites[i].transform.position, location[i],_direction,i);
            table.Add("Ellipse", newlist);
            ManagerEffective.MoveTo(Sprites[i], table, newlist);   
        }
        StartCoroutine(judgeifneedrestdepth());
    }
    Hashtable gethashtable(Vector3 position)
    {
        Hashtable args = new Hashtable();
        //這裏是設置類型,iTween的類型又很多種,在源碼中的枚舉EaseType中
        //例如移動的特效,先震動在移動、先後退在移動、先加速在變速、等等
        args.Add("easeType", iTween.EaseType.easeInOutExpo);

        //移動的速度,
       // args.Add("speed", 10f);
        //移動的整體時間。如果與speed共存那麼優先speed
        args.Add("time", 0.21f);
        //這個是處理顏色的。可以看源碼的那個枚舉。
       // args.Add("NamedValueColor", "_SpecColor");
        //延遲執行時間
        args.Add("delay", 0f);
        //移動的過程中面朝一個點
        //args.Add("looktarget", Vector3.zero);

        //三個循環類型 none loop pingPong (一般 循環 來回)	
        //args.Add("loopType", "none");
        //args.Add("loopType", "loop");	
        args.Add("loopType", "one");

        //處理移動過程中的事件。
        //開始發生移動時調用AnimationStart方法,5.0表示它的參數
     //   args.Add("onstart", "AnimationStart");
      //  args.Add("onstartparams", 5.0f);
        //設置接受方法的對象,默認是自身接受,這裏也可以改成別的對象接受,
        //那麼就得在接收對象的腳本中實現AnimationStart方法。
    //    args.Add("onstarttarget", gameObject);


        //移動結束時調用,參數和上面類似
        args.Add("oncomplete", "judgeifneedgotoevent");
        //args.Add("oncompleteparams", "end");
        args.Add("oncompletetarget", gameObject);


        //移動中調用,參數和上面類似
       // args.Add("onupdate", "judgeifneedrestdepth");
       // args.Add("onupdatetarget", gameObject);
     //   args.Add("onupdateparams", true);
        // x y z 標示移動的位置。
        args.Add("position",position);
        return args;
    }
    //計算是否需要重置渲染層級
    public IEnumerator judgeifneedrestdepth()
    {
        yield return new WaitForSeconds(0.1f);
        ResetDeep();
    }
    //判斷是否該執行回調函數了
    public void judgeifneedgotoevent()
    {
        i_havemovesprite++;
        if (i_havemovesprite >= Sprites.Length)
        {
            isruningone = false;
            i_havemovesprite = 0;
            doEvent();
        }
    }
    //根據點座標獲取橢圓的角度
    int getAngle(Vector3 point)
    {
       
        int angle = 0;
        int x = (int)(point.x -centerPos.x);
        int y = (int)(point.y - centerPos.y);
        float _angle = 0;
        if (x >=0 && y >= 0)
        {
            _angle = Mathf.Acos(x /R);
            _angle = (_angle / Mathf.PI) * 180;
        }
        else if (x < 0 && y > 0)
        {
            _angle = Mathf.Acos(x /R);
            _angle = (_angle / Mathf.PI) * 180;
        }
        else if (x < 0 && y <= 0)
        {
            _angle = Mathf.Acos(x /R);
            _angle = (_angle / Mathf.PI) * 180;
            _angle = 360 - _angle;
        }
        else if (x >= 0 && y < 0)
        {
            _angle = Mathf.Acos(x /R);
            _angle = (_angle / Mathf.PI) * 180;
            _angle = 360 - _angle;
        }
        angle = (int)_angle;
        return angle;
    }
    Vector3 GetPoint(float _angle, Vector3 _centerposition)
    {
        float hudu = (_angle / 180f) * Mathf.PI;
        float cosx = Mathf.Cos(hudu);
        float sinx = Mathf.Sin(hudu);
        float x = _centerposition.x + R * cosx;
        float y = _centerposition.y + r * sinx;
        Vector3 point = new Vector3(x, y, 0);
        return point;
    }
    //Test
    List<Vector3> getListend(Vector3 Start_point, Vector3 End_point, MYDirection _direction,int index)
    {
        List<Vector3> newlist = new List<Vector3>();
        int endAngle = getAngle(End_point);
        int StartAngle = getAngle(Start_point);
        int loacleangle = 0;
        if (_direction == MYDirection.LEFT)
        {
            if (index == (size - 1) && endAngle < 360 && endAngle > 270 )//如果是左邊最後一個
            {
                loacleangle = -(360 - endAngle + StartAngle) / 3;
            }
            else
            {
                if (Sprites.Length == 2 && endAngle <=360 && endAngle >= 270)
                {
                    loacleangle = (StartAngle - endAngle) / 3;
                }
                else
                {
                    loacleangle = (endAngle - StartAngle) / 3;
                }
                
            }
           
        }
        else
        {
            if (index == (Sprites.Length -1)&& StartAngle < 360 && StartAngle > 270)//如果是右邊最後一個
            {
                 loacleangle = (360 - StartAngle + endAngle) / 3;
            }
            else
            {
                if (Sprites.Length == 2 && StartAngle <= 360 && StartAngle >= 270)
                {
                    loacleangle = (StartAngle - endAngle) / 3;
                }
                else
                {
                    loacleangle = (endAngle - StartAngle) / 3;
                }
                
            }
        }
        Debug.Log("**********************************this Time is  new one and the name is"+Sprites[index].name);
        Debug.Log("start Position and angle is :"+Start_point+"and"+StartAngle);
        Debug.Log("end Position and angle is :" + End_point + "and" + endAngle);
        Debug.Log("local ang;e and angle is :" + loacleangle );
        float angle = (float)(StartAngle + loacleangle); 
        Vector3 centPos = centerPos;
        Vector3 tem = GetPoint(angle, centPos);
        Debug.Log("tem Position and angle is :" + tem + "and" + angle);
        newlist.Add(tem);
        angle += loacleangle;
        tem = GetPoint(angle, centPos);
        Debug.Log("tem Position and angle is :" + tem + "and" + angle);
        newlist.Add(tem);
        newlist.Add(End_point);
        return newlist;
    }
}



源碼地址:點擊打開鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章