TIL - 1

Chu_uhC·2023년 8월 7일
0

TIL

목록 보기
1/16
post-thumbnail

📄 23.08.07 ✍ Git이란

Git : 버전 관리 도구
Github : 온라인 협력 도구의 프로그램 이름

git init -> git으로 관리 시작
  
git clone /*주소*/ -> 해당 주소의 저장소 복제
  
git branch /*이름*/-> 브랜치 생성
//이름 빼고 입력시 브랜치 목록이 나옴
  
git switch /*이름*/, git checkout /*이름*/ -> 해당 브랜치로 이동
  
git add /*파일명*/, git add . -> 관리 내역에 파일을 추가, 현재 디렉토리 추가
  
git commit -m /*"메세지"*/ -> 저장소의 체크포인트를 남긴다
  
git pull /*주소*/-> 해당 주소의 저장소를 병합하여 복제
  
git push /*저장소명*/ /*브랜치명*/ -> 온라인으로 체크포인트를 보낸다
  
  • clone과 pull의 차이는 병합할지 덮을지 차이다.

  • 터미널에서 Git Bash를 사용하자.

  • 항상 사본을 만들어서 수정할 것.

🎉 한 장 요약




📄 23.08.08 ✍ 글자 띄우고 사라지기


void MakeMatchText(string text)
{
	string name = SelectName(text); //이름 불러오기, 값형은 아직 미정 

	GameObject firstCardText =
    Instantiate(MatchText, firstCard.transform.position, Quaternion.identity);
	GameObject secondCardText =
    Instantiate(MatchText, secondCard.transform.position, Quaternion.identity);
	// 자식으로 넣으면 스스로 파괴하기 전에 부모가 파괴되면서 같이 사라짐
	// 그래서 부모의 포지션 값만 받아서 따로 생성함
	firstCardText.transform.Find("Text").gameObject.GetComponent<Text>().text = name;
	secondCardText.transform.Find("Text").gameObject.GetComponent<Text>().text = name;
	// name으로 쓸 변수가 아직 정해지지 않아 따로 함수로 틀만 만들어 둠
}
    
string SelectName(string text) // 값을 받아서 name을 분류할 예정
{
	string name;

	switch (text)
{
		case "ㄱㄱㄱ":
			name = "ㄱㄱㄱ";
			break;
		case "ㅈㅈㅈ":
			name = "ㅈㅈㅈ";
			break;
		case "실패": 
			name = "실패";
			break;
		default: // 방어 코딩도 잊지 말 것
			name = "입력 실패";
			break;
	}
	return name;
}

public class MatchText : MonoBehaviour
{
    [SerializeField]
    float MoveSpeed; // 글자 올라가는 속도
    [SerializeField]
    float MoveMaxPosY; // 올라가는 Y 한계값
    [SerializeField]
    float PosY; // 선택한 카드 기준 추가될 Y값

    float CheckMovePos = 0; // MoveMaxPosY와 비교할 값

    Text Text; // 투명도 조절에 쓰일 예정

    void Awake()
    {
        Text = transform.Find("Text").GetComponent<Text>(); // Text 값 초기화
        transform.position += Vector3.up * PosY; 
        // 만들어진 위치에서 PosY만큼 추가
        // 카드의 중앙보다 위에서 나타나기 위해 추가함
    }

    void Update() // 위치, 투명도, 오브젝트 파괴 조건
    {
        transform.position += Vector3.up * MoveSpeed * Time.deltaTime;
        // 위로 움직이는 코드
        CheckMovePos += Vector3.up.y * MoveSpeed * Time.deltaTime;
        // 움직이는 vector3.y를 비교할 수 있게 float로 저장 
        Text.color = 
        new Color(Text.color.r, Text.color.g, Text.color.b, 1.0f - (CheckMovePos / MoveMaxPosY ));
        // 색깔 변경을 쉽게 하기 위해 기존에 사용하는 Color값을 불러옴
        // 알파값(a)는 255 = 1.0f(불투명)이다 그러므로 1 - (CheckMovePos / MoveMaxPosY ) 해주면 
        // MoveMaxPosY에 도달할수록 알파값이 0(투명)에 가까워진다.
        if (CheckMovePos > MoveMaxPosY) // CheckMovePos가 한계값인 MoveMaxPosY 도달하면
        {
            Destroy(gameObject); // 오브젝트를 파괴한다.
        }
    }
}

✅ SOLID에 SO가 잘 지켜졌다라고 '생각'한다.

✅ 대부분의 값을 변수로 사용하였으므로 Sprite 패치 후에 유지 보수가 편하지 않을까?

⛔ PosY값을 상수로 사용하였는데 카드 크기가 변경되면 고쳐야한다.
🔧 다음엔 Scale, Sprite의 PixelPerUnit, Sprite의 Height을 이용하여 상단 끝부분을 구해보자

⛔ 방어 코딩을 잘 하였는가?
🔧 ..

Text.color = new Color(Text.color.r, Text.color.g, Text.color.b, 1.0f - (CheckMovePos / MoveMaxPosY ))가 최선의 코드였을까?


🎉 한 장 요약




📄 23.08.09 ✍ 반복문에서 한 번만 실행하기

bool ShowHint = false;

void ShowMeTheHint() // 시점 함수 Update에서 사용하는 함수  
{
	if (ShowHint == false)
	{
		ShowHint = true; // false 값으로 변경하기 전까지 다시 실행 안됨
		GameObject cards = GameObject.Find("cards"); // cards는 card의 부모이기때문에 불러옴
		int RandomCard = UnityEngine.Random.Range(0, cards.transform.childCount); 
        // cards.transform.childCount -> cards의 자식 갯수(남은 카드 갯수)
		// 남은 카드 중에서 힌트를 줄 카드 랜덤 선택

		for (int num = 0; num < cards.transform.childCount; num++) // 카드들을 비교하기위해 사용
		{
			if (cards.transform.GetChild(RandomCard).Find("front").GetComponent<SpriteRenderer>().sprite.name 
				== cards.transform.GetChild(num).Find("front").GetComponent<SpriteRenderer>().sprite.name 
				&& RandomCard != num) 
                // RandomCard의 스프라이트 이름과 for문으로 차례대로 카드 스프라이트 이름을 비교
                // RandomCard와 for문의 카드 번호가 같으면 안됨
			{
				cards.transform.GetChild(RandomCard).GetComponent<Animator>().SetTrigger("IsHint"); 
                // 애니메이션 트리거 작동
				cards.transform.GetChild(num).GetComponent<Animator>().SetTrigger("IsHint"); 
                // 트리거 = 1회 작동
				break; // 짝을 찾으면 바로 중단해서 퍼포먼스 상향
			}
		}
	}
}

RandomCard != num 예외 처리 바로 생각나서 뿌듯함.

⛔ Update에서 사용 안하는 방법은 없었을까?
🔧 현재 상태에선 Update 에서 타이머와 함께 사용하는 게 최선.

Sprite.name으로 비교하는 방법말고 다른 방법은 무엇인가?
🔧 1. tag를 사용할 수도 있지만 태그까지 사용하기에는 배꼽이 커지는 느낌.
🔧 2. card의 스크립트에 string name을 선언하여 변별력을 추가해주고 비교.


🎉 한 장 요약




📄 23.08.10 ✍ 등장 애니메이션

IEnumerator AppearCard(List<GameObject> cardsArr)
{
    IsStartAniOff = false; // 악당들도 지키는 변신 매너
    for (int num = 0; num < cardsArr.Count; num++) // 카드 수에 따라 수정 필요 없이 실행됨
    {
        yield return new WaitForSeconds(0.15f); //0.15초 마다 하나씩
        cardsArr[num].SetActive(true); //카드를 활성화
        cardsArr[num].GetComponent<Animator>().SetTrigger("IsAppear"); // 애니메이션도 실행
        if (num == cardsArr.Count - 1) // 마지막 카드에서
        {
            yield return new WaitForSeconds(0.3f); // 0.3초(애니메이션 끝나는 시간)
            IsStartAniOff = true; // 기다렸다가 변신 완료, 게임 시작
        }
    }
}

Coroutine 을 처음으로 이해하고 사용해 봄.

start, OnEnable 함수에 애니메이션 트리거를 넣는 방법도 있다.
🔧 둘 다 오브젝트가 활성화되면 실행되는 이벤트 함수(시점 함수)이지만 '활성화 = 등장 애니메이션'은 아니라고 생각하였다.
✅ 난이도에 따라 등장하는 카드 수가 증가하므로 확장이 편한 List를 사용하였다.

Invoke와 다르게 매우 마음에 드는 기능인 Coroutine에 대하여 겉만 할짝했다.
🔧 주간 일지에서 대서 특필 한번 하자


🎉 한 장 요약




📄 23.08.11 ✍ 정지 버튼 만들기


public class PauseUI : MonoBehaviour, IPointerClickHandler //(IPointer 인터페이스)
{
    bool isTimeStop = false; // 정지 유무를 확인할 변수
    public bool IsTimeStop { get { return isTimeStop; } } // 외부로 리턴'만' 해줄 get 함수

    [SerializeField]
    Sprite StartImage; // 정지 후 바뀔 sprite, 인스펙터에서 넣어주시면 됩니다.
    Sprite PauseImage; // 처음 설정된 sprite이고 자동으로 할당됩니다.
    //위에 주석 두 줄은 협업을 위해 작성하였음
    

    void Awake()
    {
        PauseImage = GetComponent<Image>().sprite; 
        // PauseImage에 처음 설정된 sprite를 할당
    }

    public void OnPointerClick(PointerEventData eventData) // 클릭 시 이벤트
    {
        if (isTimeStop == false && gameManager.I.IsGameing == true) // 게임이 실행 중이면
        {
            GetComponent<Image>().sprite = StartImage;
            isTimeStop = true;
            Time.timeScale = 0;
            DestroyClickEffect(); // 시간이 정지되면서 
            gameManager.I.endPanel.SetActive(true);
        }
        else if (isTimeStop == true && gameManager.I.IsGameing == true)
        { //else if문을 사용한 이유는 무조건 둘 중 하나만 작동 하기 때문에!!
            GetComponent<Image>().sprite = PauseImage;
            isTimeStop = false;
            Time.timeScale = 1.0f;
            gameManager.I.endPanel.SetActive(false);
        }
    }

    void DestroyClickEffect() // 마우스를 따라다니는 이펙트를 파괴한다.
    { // 시간을 멈추면 이펙트의 애니메이션도 멈춰서 파괴해야했다.
        Transform[] ClickEffectChildArr =
        gameManager.I.ClickEffects.GetComponentsInChildren<Transform>();
        for (int num = 1; num < ClickEffectChildArr.Length; num++)
        {
            Destroy(ClickEffectChildArr[num].gameObject);
        }
    }
}

✅ 그래픽 담당 팀원과 협업을 위해 주석을 활용하였고 별도의 연락없이 잘 처리됨

✅ 팀원과 협업을 위해 주석을 활용하였다.

Time.timeScale 특정 오브젝트만 적용 혹은 예외 처리하는 방법은 없을까?
🔧 당연하게도 Time.timeScale에 영향을 받지 않는 독립적인 시간Time.unscaledDeltaTime가 있다.

Time.timeScale = 0;

float Time1 = 0;
float Time2 = 0;

Time1 += Time.deltatime; // 작동하지 않는다.
Time2 += Time.unscaledDeltaTime; // 작동한다.

애니메이션은 Animator 컴포넌트를 통하여 설정할 수있다.

🎉 한 장 요약




📔 주간 결산

1. 팀원들과 함께 만드는 프로젝트

우리가 생각하는 협업과 개발자로써의 협업은 비슷하면서도 더 깊이 서로 엮이는 것 같았다.
단순히 코드 하나 추가하는 것으로도 팀원의 기능에 버그가 발생하기도 하였다.
그러므로 팀원과의 소통에 좀 더 책임감을 가지는 게 중요하다고 생각한다.
쓰라린 기억은 잠시 잊고 함께 술잔 기울이면 친구가 되었던 시절로 돌아가보는 것도 좋을 것 같다. (틀니를 끼우며)

2. 올해 봄, 코딩을 시작하고 오늘까지의 실력

프로젝트를 하며 한 치의 망설임 없이 기능들을 만들어갔다. 지금 당장 퇴소하고 게임 뚝딱뚝딱 만들고 출시하면 캘리포니아에 별장이라도 살 수 있을 것 같다.
문제는 이 느낌이 더닝 크루거 효과라는 게 학계의 정설이다. 😭
다음 주의 나에게로 보내는 편지는 c# 전공 서적을 기초도 못 끝내고 포기한 허~접🧡 쓰레기~🧡가 되겠다.

하지만! 개발자로써는 작은 성장이지만, 코드를 그리던 나라는 개발자로써는 위대한 성장인 건 누구도 부정할 수 없다.

📌 기억해야 할 이번 주 키워드

  • 예외 처리 하는 법
if (EatDinner == true) // 이렇게 쓰지말고
{
    if (WashFace == true)
    {
        if (SayGoodNight == true)
        {
/*아도겐*/  Sleep();
        }
    }
}
-----------------------------------------
if (EatDinner == false) // 이런 식으로 처리하는 게 보기 좋다
{
    return;
}
if (WashFace == false || SayGoodNight == false)
{
    return;
}

Sleep();
  • 코루틴 (Coroutine)
IEnumerator Func()
{
    Time.timeScale = 0f;
    
    yield return new WaitForSecondsRealtime(1.0f); // 현실 시간으로 1초 후
    Debug.Log("1초 후..") // output : 1초 후..
    yield return new WaitForSeconds(1.0f); // 게임 시간으로 1초 후
    Debug.Log("1초 후..") // 게임 시간을 멈췄기에 나오지 않는다.
}
profile
ChuNyan

0개의 댓글