유용한 Unity & C# 관련 링크

C#/Unity|2020. 1. 19. 13:58

-Unity Techknowledge Tutorials

https://catlikecoding.com/unity/tutorials/

-Unity Open Source Asset List

https://unitylist.com/

-Git OpenSource - UnityPakageManager(UPM) supported 
https://openupm.com/

https://github.com/starikcetin/awesome-upm

https://github.com/baba-s/awesome-unity-open-source-on-github

-Unity의 관련된 Utility Post가 있는 개인 블로그

http://www.createdbyx.com/

-Unity Git Repository 

https://github.com/neuecc (UniRx 개발자)

https://github.com/sinbad (Ogre Engine 개발자)

https://github.com/redbluegames

'C# > Unity' 카테고리의 다른 글

유니티 이동 컴포넌트 (Mover)  (0) 2019.09.14
유니티 클릭 컴포넌트 (Clickable)  (0) 2019.09.14
유니티 Android native 사운드 적용  (0) 2019.09.14

댓글()

유니티 이동 컴포넌트 (Mover)

C#/Unity|2019. 9. 14. 18:46

일반적으로 유니티에서 게임오브젝트를 이동시키는 방법은 Rigidbody를 이용한 물리 법칙을 통한 계산이나 Transform에 관련된 함수를 사용하는 것이다. 이는 Platformer 장르나 물리법칙이 적용된 게임에는 적합하나 RTS나 Defense장르에서 사용하기는 부적합하다. 그래서 목표지까지 이동이나 다른 GameObject를 따라가는 로직을 구현하기 위해 컴포넌트를 제작했다.

ToGoal함수를 이용해 목표지(Vector)까지 이동가능하며 ToFollow함수를 이용해 적을 따라가게 할 수 있다.

[DisallowMultipleComponent]
public class Mover : MonoBehaviour {
    public enum MoveType {
        None, Goal, Follow
    }
    public enum EndEvent {
        None, DestoryGameObject, DestroyComponent, DeactiveGameObject
    }

    public float speed;
    public float stopDistance = 0.1f;
    public MoveType moveType;
    public EndEvent endEvent;

    public Vector3 destination;
    public GameObject target;

    private List<Vector3> nextGoals = new List<Vector3>();
    private event Action OnCompleted;
    private event Action OnFailed;


    public bool IsMoving() {
        return moveType != MoveType.None;
    }

    public Mover SetSpeed(float _speed) {
        speed = _speed;
        return this;
    }
    public Mover SetEndEvent(EndEvent _endEvent) {
        endEvent = _endEvent;
        return this;
    }

    public void ToGoal(Vector3 _destination, Action completeAct = null) {
        destination = _destination;
        OnCompleted += completeAct;
        moveType = MoveType.Goal;
    }

    public void ToGoal(List<Vector3> desList, Action completeAct = null) {
        if(desList.Count == 0)
            return;
        ToGoal(desList[0], completeAct);
        desList.RemoveAt(0);
        nextGoals = desList;
    }

    public void ToFollow(GameObject _target) {
        ToFollow(_target, null, null);
    }
    public void ToFollow(GameObject _target, Action completeAct) {
        ToFollow(_target, completeAct, null);
    }
    public void ToFollow(GameObject _target, Action completeAct, Action failAct) {
        OnCompleted += completeAct;
        OnFailed += failAct;
        target = _target;
        moveType = MoveType.Follow;
    }



    public void Stop() {
        ResetState();
    }

    private void Update() {
        if(moveType == MoveType.None)
            return;

        if(moveType == MoveType.Goal) {//목표지점까지 이동
            transform.position = Vector3.MoveTowards(transform.position, destination, speed * Time.deltaTime);

            if(Vector3.Distance(transform.position, destination) < stopDistance) {
                if(nextGoals.Count == 0) {
                    transform.position = destination;
                    OnCompleted?.Invoke();
                    ResetState();
                    ExcuteEndEvent();
                    return;
                } else {
                    destination = nextGoals[0];
                    nextGoals.RemoveAt(0);
                    return;
                }
            }
        } else if(moveType == MoveType.Follow) {//목표 타겟한테 이동
            if(target == null) {
                OnFailed?.Invoke();
                ResetState();
                ExcuteEndEvent();
                return;
            }
            transform.position = Vector3.MoveTowards(transform.position, target.transform.position, speed * Time.deltaTime);
            if(Vector3.Distance(transform.position, target.transform.position) < stopDistance) {
                transform.position = target.transform.position;
                OnCompleted?.Invoke();
                ResetState();
                ExcuteEndEvent();
            }
        }
    }


    private void ResetState() {
        moveType = MoveType.None;
        OnFailed = null;
        OnCompleted = null;
    }

    private void ExcuteEndEvent() {
        if(endEvent == EndEvent.DestroyComponent) {
            Destroy(this);
        } else if(endEvent == EndEvent.DestoryGameObject) {
            Destroy(gameObject);
        } else if(endEvent == EndEvent.DeactiveGameObject) {
            gameObject.SetActive(false);
        }
    }
}

'C# > Unity' 카테고리의 다른 글

유용한 Unity & C# 관련 링크  (0) 2020.01.19
유니티 클릭 컴포넌트 (Clickable)  (0) 2019.09.14
유니티 Android native 사운드 적용  (0) 2019.09.14

댓글()

유니티 클릭 컴포넌트 (Clickable)

C#/Unity|2019. 9. 14. 18:32

유니티 게임오브젝트의 클릭은 OnMouseUp이나 OnMouseDown같은 콜백함수로 구현되어있다.

하지만 Double Click이나 Long Click같은 로직은 코루틴을 이용해서 구현해야 하는데 

쉽게 사용하기 위해 컴포넌트 방식으로 구현해 보았다. (2D 기반이며 Collider가 있어야한다)

내부로직은 코루틴으로 작동하며 event를 등록하거나 Regist함수를 호출함으로서 사용가능하다.

개선사항은 Clickable 컴포넌트간의 우선순위 설정이 필요할 수도 있겠다. 

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

[DisallowMultipleComponent]
[RequireComponent(typeof(Collider2D))]
public class Clickable : MonoBehaviour {
    public static float DOUBLE_INTERVAL=0.2f;
    public static float LONG_INTERVAL=0.8f;

    public bool isOnce = true;
    public bool isDouble;
    public bool isLong;

    public event Action OnOnceClicked;
    public event Action OnDoubleClicked;
    public event Action OnLongClicked;

    private int downCount;
    private float clickTime;

    private Coroutine doubleCoroutine;
    private Coroutine longCoroutine;


    public Clickable RegistInOnce(Action act) {
        isOnce = true;
        OnOnceClicked += act;
        return this;
    }
    public Clickable RegistInDouble(Action act) {
        isDouble = true;
        OnDoubleClicked += act;
        return this;
    }
    public Clickable RegistInLong(Action act) {
        isLong = true;
        OnLongClicked += act;
        return this;
    }
    public Clickable ClearInOnce(Action act) {
        OnOnceClicked = null;
        return this;
    }
    public Clickable ClearInDouble(Action act) {
        OnDoubleClicked = null;
        return this;
    }
    public Clickable ClearInLong(Action act) {
        OnLongClicked = null;
        return this;
    }

    private void OnMouseDrag() {
        clickTime += Time.deltaTime;
    }
    private void OnMouseUp() {
        clickTime = 0f;
    }

    private void OnMouseDown() {
        clickTime = 0f;
        downCount++;

        if(isOnce && !isDouble && !isLong) {
            OnOnceClicked?.Invoke();
            return;
        }
        if(isDouble && doubleCoroutine == null) {
            doubleCoroutine = StartCoroutine(CoWaitDouble());
        }
        if(isLong && longCoroutine == null) {
            longCoroutine = StartCoroutine(CoWaitLong());
        }
    }

    private IEnumerator CoWaitDouble() {
        float startTime = Time.time;
        int curCount = downCount;
        while(true) {
            if(curCount < downCount) {
                OnDoubleClicked?.Invoke();
                break;
            }

            if(startTime + DOUBLE_INTERVAL < Time.time) {
                if(longCoroutine == null) {
                    OnOnceClicked?.Invoke();
                }
                break;
            }
            yield return null;
        }
        doubleCoroutine = null;
    }
    private IEnumerator CoWaitLong() {
        float startTime = Time.time;
        while(true) {
            if(!Input.GetMouseButton(0)) {
            	if (startTime+DOUBLE_INTERVAL<Time.time) {
                    OnOnceClicked?.Invoke();
                }
                break;
            }

            if(startTime + LONG_INTERVAL < Time.time) {
                OnLongClicked?.Invoke();
                break;
            }

            yield return null;
        }
        longCoroutine = null;
    }
}

'C# > Unity' 카테고리의 다른 글

유용한 Unity & C# 관련 링크  (0) 2020.01.19
유니티 이동 컴포넌트 (Mover)  (0) 2019.09.14
유니티 Android native 사운드 적용  (0) 2019.09.14

댓글()