InputSytem - InvokeEvent

`InvokeEvent`는 버튼 이벤트처럼 콜백 메서드를 등록해서 사용한다.
    private Vector2 curMovementInput;
    public void OnMove(InputAction.CallbackContext context)
    {
        if (context.phase == InputActionPhase.Performed)
        {
            curMovementInput = context.ReadValue<Vector2>();
        }
        else if (context.phase == InputActionPhase.Canceled)
        {
            curMovementInput = Vector2.zero;
        }
    }`InputSystem`에 등록해둔 키값의 정보가 `context`에 저장되고, `ReadValue`로 불러올 수 있다.
또한 `phase`로 키값이 눌러졌을 때, 뗐을 때 등등의 상태에 따라 어떤 작업을 수행할지 정할 수 있다.
| Phase | 설명 | 
| Disabled | 동작이 비활성화되어 입력을 받을 수 없다. | 
| Waiting | 동작이 활성화되어 입력을 기다리고 있다. | 
| Started | 입력 시스템이 동작과 상호 작용을 시작하는 입력을 받았다.(키가 눌러졌다.) | 
| Performed | 동작과의 상호 작용이 완료되었다. (키가 눌러지고 있다.) | 
| Canceled | 동작과의 상호 작용이 취소되었다. (키를 뗐다.) | 
공식 문서▼
https://docs.unity3d.com/Packages/com.unity.inputsystem@1.5/manual/Actions.html#action-callbacks
데미지 입는 Flash 애니메이션 - Coroutine(코루틴)
    public void Flash()
    {
        if (coroutine != null)
        {
            StopCoroutine(coroutine);
        }
        image.enabled = true;
        image.color = new Color(1f, 100f / 255f, 100f / 255f);
        coroutine = StartCoroutine(FadeAway());
    }
    private IEnumerator FadeAway()
    {
        float startAlpha = 0.3f;
        float a = startAlpha;
        while (a > 0)
        {
            a -= (startAlpha / flashSpeed) * Time.deltaTime;
            image.color = new Color(1f, 100f / 255f, 100f / 255f, a);
            yield return null;
        }
        image.enabled = false;
    }데미지를 입었을 때 화면이 빨간 Falsh효과를 내도록하는 코드이다.
여기서 `(startAlpha / flashSpeed)`는 시간당 알파 값의 변화량을 나타낸다. 그리고 프레임 레이트에 관계없이 일정한 속도로 알파 값이 변경되도록 하기 위해 `Time.deltaTime`을 곱해준다.
코루틴은 `yield return` 이 있어야 하는데, `null`을 리턴해주면 코루틴이 다음 프레임까지 일시 중지되도록 한다.
즉, `yield return null;`은 "하나의 프레임을 대기한다"는 의미이다.
낮과 밤 구현 - Directional Light, Gradient, AnimationCurve
유니티에서 `Directional Light`로 Sun을 표현한다.
그래서 `Rotation`의 `x`값을 0~360도로 바꾸면 낮과 밤이 바뀌는듯한 현상을 볼 수 있다.

Lighting의 Environment창을 보면 Lighting의 Intensity Multiplier, Reflections의 Intensity Multiplier가 있다.
`Intensity Multiplier`는 빛의 강도인데, 낮에는 빛의 강도가 쎄고 밤에는 빛의 강도가 약하게 하기 위해 코드로 조절해야한다.

우선 낮일 때와 밤일 때의 `Directional Light`를 각각 둔다.


Sun은 노란색, Moon은 푸르스름한 색으로 설정한다.
    [Header("Sun")]
    public Light sun;
    public Gradient sunColor;
    public AnimationCurve sunIntensity;
    [Header("Moon")]
    public Light sun;
    public Gradient sunColor;
    public AnimationCurve sunIntensity;
    [Header("Other Lighting")]
    public AnimationCurve lightingIntensityMultiplier;
    public AnimationCurve reflectionIntensityMultiplier;
`Gradient`는 그라데이션이라 생각하면 된다. 색이 점점 변하는 것을 표현해준다.
`AnimationCurve`는 Sun과 Moon의 조명을 서서히 늘려주기 위해 사용된다.
    void Update()
    {
        time = (time + timeRate * Time.deltaTime) % 1.0f;
    }시간이 점점 지나가는걸 계산하는건데, `1.0f`를 나머지 연산하는 이유는 연산 결과를 0과 1사이로 유지시켜주기 위함이다.
`Directional Light`가 0~360도로 회전하는데, 이 값을 `0f~1.0f`로 매핑시켰다. 그래서 시간도 0과 1사이로 유지시켜준다.
lightSource.transform.eulerAngles = (time - (lightSource == sun ? 0.25f : 0.75f)) * noon * 4f;하루가 `0f~ 1.0f`로 변화하는데 정오는 `0.5f`이다.
그런데 360도에서 0.5f는 180도이기 때문에 Sun일 때는 `time(0.5f) - 0.25f`를 해줘야 90도가 나온다.
그리고 `noon`이라는 90도를 곱해준다.
그런데 90도에다가 0.25를 곱하면 90이 안나온다. 그래서 `4f`까지 곱해주는 것이다. (90*4 = 360, 360*0.25 = 90)
콜라이더 크기 설정


박스 콜라이더의 크기를 설정할 때 3D공간에서는 크기를 딱 맞추기가 어렵다.
그래서 나는 이때까지 빨간점부분에 보이는 정육각형의 면을 한 번 클릭하여 2D 화면처럼 만든 후 콜라이더 크기를 조절했다.
그런데 튜터님 한 분이 코드로 콜라이더 크기를 딱 맞추게 하는 방법을 알려주셨다!!..
public class AutoCollider : MonoBehaviour
{
#if UNITY_EDITOR
    private void OnValidate()
    {
        Renderer mr = GetComponentInChildren<MeshRenderer>();
        if (mr == null) mr = GetComponentInChildren<SkinnedMeshRenderer>();
        var box = GetComponentInChildren<BoxCollider>();
        box.center = mr.bounds.center - transform.position;
        box.size = mr.bounds.size;
        UnityEditor.EditorApplication.delayCall += () =>
        {
            DestroyImmediate(this);
        };
    }
#endif
}위의 스크립트를 작성해서

오브젝트에 해당 스크립트를 부착해주면 위의 사진처럼 오브젝트 크기에 딱! 맞는 콜라이더 크기가 설정된다.
코드를 한 번 분석해보겠다.
#if UNITY_EDITOR
#endif우선 위의 코드는 전처리 지시문이다.
둘 사이에 있는 코드는 특정 조건에서만 컴파일되도록 제어된다.
`#if UNITY_EDITOR`라는 조건이 있는데, 이 조건은 코드가 Unity 에디터 환경에서 실행될 때만 포함되도록 하는 조건문이다. 즉, 빌드된 게임에는 포함되지 않고, 개발 중에 에디터상에만 사용되는 코드이다.
        Renderer mr = GetComponentInChildren<MeshRenderer>();
        if (mr == null) mr = GetComponentInChildren<SkinnedMeshRenderer>();우선 해당 오브젝트의 `MeshRenderer`를 불러온다.
        var box = GetComponentInChildren<BoxCollider>();
        box.center = mr.bounds.center - transform.position;
        box.size = mr.bounds.size;`BoxCollider` 컴포넌트를 불러온 후 오브젝트의 ` MeshRenderer`의 경계의 중심과 사이즈를 박스 콜라이더에 매핑한다.
`MeshRenderer`의 `bounds`는 월드 좌표계에서의 경계상자를 나타낸다.
`BoxCollider`의 `center`는 로컬 좌표계에서의 중심을 나타낸다.
그래서 로컬 좌표계로 변환하기 위해 `mr.bounds.center - transform.position`을 빼주는 것이다.
        UnityEditor.EditorApplication.delayCall += () =>
        {
            DestroyImmediate(this);
        };Unity 에디터 내에서 특정 작업이 완료된 후 스크립트가 실행되도록 예약하는 코드이다.
`delayCall` 델리게이트를 사용하여 다음 프레임이 시작될 때 `DestroyImmediate(this)`를 호출하여 해당 객체를 즉시 파괴하도록 예약한다.
그래서 첨부한 gif를 보면 AutoCollider 스크립트를 부착했는데 바로 사라지는 것을 볼 수 있다.
Static 옵션

오브젝트에 Static옵션이 켜져있는 것을 볼 수 있다.
이는 오브젝트가 움직이지 않고 고정된 상태에서 렌더링 되는 경우에 유용하다.
예를 들면 그냥 돌같이 배경적인 요소들 말이다.
'스파르타 게임개발종합반(Unity) > TIL - 본캠프 매일 공부 기록' 카테고리의 다른 글
| 2024.05.29 TIL - 디자인 패턴(상) 특강 정리 (2) | 2024.05.29 | 
|---|---|
| 2024.05.28 TIL - 디버깅 특강 정리 (0) | 2024.05.28 | 
| 2024.05.24 TIL - Ray, Raycast, IsGrounded, 땅 충돌 체크 (0) | 2024.05.24 | 
| 2024.05.23 TIL - 오브젝트 풀링, UnityEngine.Pool, ObjectPool (0) | 2024.05.23 | 
| 2024.05.22 TIL - SoundManager로 배경음과 효과음 관리 및 재생하기 (0) | 2024.05.22 | 
 
			
			 
				
			
댓글