【Unity3D開發】簡單工廠模式

本文同時發布至我的個人博客,點擊進入我的個人博客閱讀。本博客供技術交流與經驗分享,可自由轉載。轉載請在評論區或私信簡單通知,感謝!

游戲需求

  • 實現點擊效果。
  • Plane 或其他物體做地面, tag 為Finish
  • 點擊地面后,出現一個圓形攻擊標記,兩秒后自動消失。注意:該攻擊標記不能擋住點擊。(Primitive Objects / Cylinder)
  • 請使用一個簡單工廠創建、管理這些的標記,并自動收回這些標記(注意,這些對象創建后,放在列表內,不必釋放)。

效果展示:

實現過程

(一)CameraPlane 的基本配置

? 設置好Camera的位置與角度,并設置視圖為正交,如下圖:

? 為方便顯示,創建Plane后再添加一個Material,使其變為藍色,如下圖:

(二)定義并實現EsayFactory

? 首先創建一個繼承MonoBehaviourBasecode類,自定義一個namespace并引用,在該namespace定義并實現EsayFactory類。

? EsayFactory類為工廠類,它負責管理Cylinder的創建、停用和重復使用。重復使用的實現主要通過講使用完畢的Cylinder加入一個List中,在需要時重新拿出使用的方法來實現。這樣做的好處是,避免了重復地創建和銷毀游戲對象,能減少游戲的內存消耗。

? 需要注意的是:嚴格控制單實例,避免用戶創建多個EsayFactory對象。

public class EsayFactory : System.Object
{
    public List<GameObject> markList = new List<GameObject>();
    private static EsayFactory _factory;
    private Camera _camera;
    
    //控制單實例
    public static EsayFactory GetInstance()
    {
        if (_factory == null)
        {
            _factory = new EsayFactory();
            _factory._camera = Camera.main;
        }
        return _factory;
    }

    public void placeAttackMark(Vector3 target)
    {
        Ray _ray = _camera.ScreenPointToRay(target);
        RaycastHit _hit;
        if (Physics.Raycast(_ray, out _hit))
        {
            if (_hit.collider.gameObject.tag.Contains("Finish"))
            {
                GameObject attackMark;
                //List中若無可用對象則創建新對象
                if (markList.Count == 0)
                {
                    attackMark = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
                    //避免Cylinder擋住點擊
                    attackMark.GetComponent<Collider>().enabled = false;
                }
                //若有可用對象則拿出重用
                else
                {
                    attackMark = markList[0];
                    markList.RemoveAt(0);
                }
            attackMark.transform.SetParent(_hit.collider.gameObject.transform);
            attackMark.transform.position = _hit.point;
              //添加一個自定義的實現了延時2s刪除功能的組件
            DelayToDelete _delay = attackMark.AddComponent<DelayToDelete>();
            _delay.delete(markList, attackMark, 2.0f);
        }
    }
}

(三)實現延時刪除

? DelayToDelete繼承MonoBehaviour類,實現了兩個方法:私有方法delayTo()實現了具體延時功能的實現,公有方法delete()實現了具體的2秒后刪除的功能需求。這里采用了Action類來代替Invoke()方法,其好處是拓展性更強,可讀性也更高。StartCoroutineMonoBehaviour中的一個調用協同程序的方法,通過使用 yield return new WaitForSeconds(delaySeconds);可以實現延時一定實現后執行。

public class DelayToDelete : MonoBehaviour
{
    public void delete(List<GameObject> markList, GameObject attackMark, float  delaySeconds)
    {
        StartCoroutine(delayTo(() =>
        {
          //移出游戲范圍并加入List中等待重用
            attackMark.transform.position = new Vector3(0f, -99f, 0f);
            markList.Add(attackMark);
        }
        , 2.0f));
    }

    private IEnumerator delayTo(Action action, float delaySeconds)
    {
      //延時執行action();
        yield return new WaitForSeconds(delaySeconds);
        action();
    }
}

(四)完成Basecode

? Basecode類主要負責每幀檢查用戶是否做了點擊事件,若點擊則調用placeAttackMark方法:

public class Basecode : MonoBehaviour {
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            Vector3 point = Input.mousePosition;
            EsayFactory.GetInstance().placeAttackMark(point);
        }
    }
}
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,251評論 25 708
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,951評論 6 342
  • 重讀《向死而生》,心有所感 向死而生,大概只有在鬼門關走過一遭的人才會真正明白生的可貴和如何過好這一生吧,才會體會...
    你就是我最美的未來閱讀 302評論 0 0
  • 你說過,但你沒做。 你沒說,并也沒做。 你說了,并且做了。 你沒說,但你做了
    風與光閱讀 180評論 0 1