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 |
댓글