동구의_C# & Unity_개발일지
2024.02.05 내일배움캠프 30일차 TIL_Unity (숙련, 알고리즘) 본문
유니티 숙련 주차에 이어 2D에서 3D로 넘어간다!
강의를 들으며 개인과제을 하였다.
강의로 3D게임을 만들며 개인과제로 ATM 시스템을 만들어 볼 것이다.
필수요구사항에 ATM 화면 구성을 구현하였다.
필수요구사항
1. ATM 화면 구성 (완료)
2. 입금 기능 (미완료)
3. 출금 기능 (미완료)
선택요구사항
1. 통화 단위 적용 (난이도 - ★☆☆☆☆)
2. 금액 입력시 숫자만 입력 (난이도 - ★☆☆☆☆)
3. 로그인 기능 (난이도 - ★★☆☆☆)
4. 회원가입 (난이도 - ★★★★☆)
5. 송금 기능 (난이도 - ★★★★☆)
알고리즘 코드카타 16일차
정수 내림차순으로 배치하기
문제 설명
함수 solution은 정수 n을 매개변수로 입력받습니다. n의 각 자릿수를 큰것부터 작은 순으로 정렬한 새로운 정수를 리턴해주세요. 예를들어 n이 118372면 873211을 리턴하면 됩니다.
3D 게임 기초 개발
Survial 프로젝트 셋팅
프레이어 만들기
플레이어 상태 및 UI
플레이어 데미지 처리
01. 핵심 내용
1-1) Light 컴포넌트
- 라이트 소스: 게임 또는 3D 랜더링에 광원을 추가하는 데 사용됩니다. 이것은 특정 위치 또는 방향에서 발생하는 빛을 나타냅니다.
- 유형: 라이트는 여러 유형이 있습니다. 이러한 유형 중 몇 가지는 다음과 같습니다:
- 점 광원(Point Light): 특정 지점에서 모든 방향으로 빛을 발산하는 라이트입니다.
- 방향성 라이트(Directional Light): 특정 방향에서 모든 객체를 비추는 라이트입니다. 이 라이트는 거리에 관계없이 동일한 강도로 모든 객체를 비춥니다.
- 스포트라이트(Spot Light): 특정 방향으로 원뿔형의 빛을 발산하는 라이트입니다.
- 영역 라이트(Area Light): 특정 영역에서 발생하고 그 주변에 빛을 발산하는 라이트입니다(예: 실내 조명).
- 속성: 각 라이트에는 여러 속성이 있습니다. 이러한 속성에는 위치, 방향, 강도(intensity), 색상(color), 범위(range), 각도(angle) 등이 포함됩니다.
- 그림자: 라이트는 그림자를 생성할 수 있습니다. 라이트와 객체 사이의 관계에 따라 그림자는 라이트가 부딪히는 객체 뒤에 생성됩니다.
- 성능: 라이트는 렌더링 성능에 큰 영향을 미칩니다. 많은 라이트를 사용하면 특히 동적 그림자가 포함된 경우 렌더링 성능에 부정적인 영향을 미칠 수 있습니다. 따라서 최적화는 중요한 고려사항입니다.
- 빛 반사 및 산란: 라이트는 표면에 부딪히고 반사되거나 다른 방향으로 산란되어 재질과 표면의 실제성을 나타냅니다. 이러한 효과는 물리 기반 렌더링(PBR)에서 중요한 요소입니다.
1-2) 스카이박스
게임 세계의 배경을 둘러싸는 환경 매핑 기술입니다. 큐브 맵(Cube Map)과 구체형 스카이박스(Sphere Map) 등이 있으며, 주로 다음과 같은 특징을 가집니다:
- 스카이박스는 6개의 텍스처로 구성된 큐브 맵 또는 하나의 구체로 텍스처가 매핑된 구체형 스카이박스로 구성됩니다.
- Unity에서는 씬의 배경으로 사용되며, 게임 환경을 확장시키는데 활용됩니다.
- 주로 하늘, 구름, 산 등의 자연적인 배경을 표현하는 데 사용됩니다.
- 미리 만들어진 스카이박스를 사용하거나 직접 만들어서 Unity에서 적용할 수 있습니다.
- 게임 중에 스카이박스를 동적으로 변경하여 낮과 밤 등의 시간대나 특정 이벤트에 맞게 배경을 변화시킬 수 있습니다.
- 성능에 영향을 미치므로 최적화에 주의해야 합니다.
1-3) Rigidbody - ForceMode
- Force: 힘을 지속적으로 적용합니다.
- Rigidbody.AddForce(Vector3 force, ForceMode.Force);
- Acceleration: 가속도를 적용합니다. 이전 힘의 누적에 따라서 점진적으로 더 빠르게 움직이게 됩니다.
- Rigidbody.AddForce(Vector3 force, ForceMode.Acceleration);
- Impulse: 순간적인 힘을 적용합니다. 짧은 시간에 갑작스러운 움직임이 발생합니다.
- Rigidbody.AddForce(Vector3 force, ForceMode.Impulse);
- VelocityChange: 변화하는 속도를 적용합니다. 물체의 현재 속도를 변경하면서 움직입니다.
- Rigidbody.AddForce(Vector3 force, ForceMode.VelocityChange);
이러한 ForceMode를 적절히 활용하여 게임 오브젝트에 원하는 물리적인 움직임과 효과를 부여할 수 있습니다.
02. 핵심 내용
2-1) 인터페이스 복습
인터페이스를 통해 클래스들은 공통적인 동작을 정의하고, 이러한 동작들을 구현하는 클래스들은 해당 인터페이스를 구현(implement)함으로써 공통 규약을 준수할 수 있습니다.
인터페이스를 설명하는 주요 특징은 다음과 같습니다.
- 추상화: 인터페이스는 추상적인 개념으로, 실제로 구현된 메서드가 없고, 메서드의 시그니처만을 가집니다. 따라서 인터페이스는 인스턴스화될 수 없으며, 구현체가 필요합니다.
- 메서드 시그니처: 인터페이스는 구현 클래스가 반드시 구현해야 하는 메서드들의 시그니처를 정의합니다. 메서드의 이름, 매개변수, 반환 타입이 포함됩니다.
- 다중 상속 가능: 클래스는 하나의 클래스만 상속받을 수 있지만, 여러 인터페이스를 동시에 구현할 수 있습니다. 이를 통해 다중 상속을 흉내내는 것이 가능합니다.
- 강제적 구현: 클래스가 인터페이스를 구현하면, 인터페이스에서 정의한 모든 메서드를 반드시 구현해야 합니다. 이로 인해 클래스는 인터페이스에 정의된 동작을 강제로 구현하게 됩니다.
- 인터페이스 간 확장: 인터페이스는 다른 인터페이스를 확장(extends)할 수 있습니다. 이를 통해 더 큰 범위의 공통 동작을 정의할 수 있습니다.
03. 핵심 내용
3-1) Invoke
- Invoke(string methodName, float time): 지정된 시간(time) 후에 지정된 메서드(methodName)를 실행합니다.
- methodName: 실행할 메서드의 이름을 문자열로 지정합니다.
- time: 메서드를 실행할 시간을 초 단위로 지정합니다.
using UnityEngine;
public class ExampleScript : MonoBehaviour
{
private void Start()
{
Invoke("DelayedMethod", 2.0f);
}
private void DelayedMethod()
{
Debug.Log("This method is called after 2 seconds.");
}
}
3-2) Invoke Repeating
- InvokeRepeating(string methodName, float time, float repeatRate): 지정된 시간(time) 후에 지정된 메서드(methodName)를 주기적으로 반복해서 실행합니다.
- methodName: 실행할 메서드의 이름을 문자열로 지정합니다.
- time: 메서드를 처음 실행할 때까지의 시간을 초 단위로 지정합니다
- .repeatRate: 메서드를 반복해서 실행할 주기를 초 단위로 지정합니다.
csharpCopy code
using UnityEngine;
public class ExampleScript : MonoBehaviour
{
private void Start()
{
InvokeRepeating("RepeatingMethod", 2.0f, 3.0f);
}
private void RepeatingMethod()
{
Debug.Log("This method is called every 3 seconds after 2 seconds delay.");
}
}
3-3) TryGetComponent
TryGetComponent는 Unity에서 사용하는 메서드로, 게임 오브젝트의 컴포넌트를 가져오는 기능을 제공합니다. 이 메서드를 사용하면 특정 컴포넌트가 게임 오브젝트에 연결되어 있는지 확인하고, 연결되어 있다면 해당 컴포넌트를 가져올 수 있습니다.
TryGetComponent 메서드의 형식은 다음과 같습니다.
public bool TryGetComponent<T>(out T component) where T : Component;
- T: 가져오려는 컴포넌트의 타입입니다. MonoBehaviour를 상속한 컴포넌트는 모두 사용 가능합니다.
- component: 컴포넌트를 가져올 때 사용되는 out 매개변수입니다.
# 사용법
using UnityEngine;
public class ExampleScript : MonoBehaviour
{
private void Start()
{
// 게임 오브젝트에 Rigidbody 컴포넌트가 있는지 확인하고 가져옵니다.
Rigidbody rb;
if (TryGetComponent<Rigidbody>(out rb))
{
// Rigidbody 컴포넌트가 있다면 해당 컴포넌트로 원하는 동작을 수행합니다.
rb.AddForce(Vector3.up * 100f);
}
else
{
// Rigidbody 컴포넌트가 없다면 다른 처리를 수행합니다.
Debug.Log("Rigidbody component not found.");
}
}
}
TryGetComponent는 컴포넌트가 없어도 예외를 발생시키지 않고, 컴포넌트가 있으면 해당 컴포넌트를 가져와서 사용할 수 있습니다. 이를 통해 더 안전하게 컴포넌트를 가져오고 사용할 수 있습니다.
중요한 기능들을 정리해서 알아보자!
private void Move()
{
Vector3 dir = transform.forward * curMovementInput.y + transform.right * curMovementInput.x;
dir *= moveSpeed;
dir.y = _rigidbody.velocity.y;
_rigidbody.velocity = dir;
}
플레이어를 이동시키는 기능을 구현한 코드이다.
현재 입력값(curMovementInput)을 기반으로 플레이어의 이동 방향을 결정한다.
dir *= moveSpeed : 이동 방향(dir)에 이동 속도(moveSpeed)를 곱하여 실제로 플레이어가 이동할 속도를 결정한다.
void CameraLook()
{
camCurXRot += mouseDelta.y * lookSensitivity;
camCurXRot = Mathf.Clamp(camCurXRot,minXLook,maxXLook);
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivity, 0);
}
카메라의 회전을 제어하는 메서드이다.
private bool IsGrounded()
{
Ray[] rays = new Ray[4]
{
new Ray(transform.position + (transform.forward * 0.2f) + (Vector3.up * 0.01f) , Vector3.down),
new Ray(transform.position + (-transform.forward * 0.2f)+ (Vector3.up * 0.01f), Vector3.down),
new Ray(transform.position + (transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
new Ray(transform.position + (-transform.right * 0.2f) + (Vector3.up * 0.01f), Vector3.down),
};
for(int i = 0; i < rays.Length; i++)
{
if (Physics.Raycast(rays[i], 0.1f, groundLayerMask))
{
return true;
}
}
return false;
}
이 코드는 플레이어가 땅에 닿았는지 여부를 확인하기 위해 레이캐스트를 사용하는 메서드이다.
Physics.Raycast(rays[i], 0.1f, groundLayerMask) : 각 레이를 이용하여 땅과의 충돌을 검사한다. rays[i]는 현재 레이캐스트가 사용할 레이를 나타낸다. 0.1f는 레이의 최대 거리를 나타낸다. 레이가 땅과 충돌하는지 확인하기 위해 사용된다. groundLayerMask는 충돌을 검사할 레이어를 지정한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CampFire : MonoBehaviour
{
public int damage;
public float damageRate;
private List<IDamagable> thingsToDamage = new List<IDamagable>();
private void Start()
{
InvokeRepeating("DealDamage", 0, damageRate);
}
void DealDamage()
{
for(int i =0;i<thingsToDamage.Count;i++)
{
thingsToDamage[i].TakePhysicalDamage(damage);
}
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.TryGetComponent(out IDamagable damagable))
{
thingsToDamage.Add(damagable);
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject.TryGetComponent(out IDamagable damagable))
{
thingsToDamage.Remove(damagable);
}
}
}
캠프 파이어을 만들 수 있는 코드이다.
public class DamageIndicator : MonoBehaviour
{
public Image image;
public float flashSpeed;
private Coroutine coroutine;
public void Flash()
{
if(coroutine != null)
{
StopCoroutine(coroutine);
}
image.enabled = true;
image.color = Color.red;
coroutine = StartCoroutine(FadeAway());
}
private IEnumerator FadeAway()
{
float startAlpha = 0.3f;
float a = startAlpha;
while(a > 0.0f)
{
a -= (startAlpha / flashSpeed) * Time.deltaTime;
image.color = new Color(1.0f, 0.0f, 0.0f, a);
yield return null;
}
image.enabled = false;
}
}
이 코드는 데미지를 입었을 때 화면에 빨간색 플래시를 표시하는 기능을 구현한 코드이다.
private IEnumerator FadeAway() : 플래시가 서서히 사라지는 애니메이션을 구현하는 코루틴이다. 시작할 때, startAlpha값을 사용하여 초기 투명도를 설정한다. while 루프를 통해 투명도를 서서히 감소시킨다. 각 루프마다 flashSpeed와 Time.deltaTime 값을 곱하여 투명도를 조절한다. 투명도가 0 이하로 떨어지면 이미지를 비활성화하여 화면에서 숨긴다.
개인 과제 - 화면 구성
Git-Hub READM 작성
지금까지 이뤄왔던 ERADME을 전체적으로 작성해 보았다.
'Unity' 카테고리의 다른 글
2024.02.07 내일배움캠프 32일차 TIL_Unity (숙련, 알고리즘) (0) | 2024.02.07 |
---|---|
2024.02.06 내일배움캠프 31일차 TIL_Unity (숙련, 알고리즘) (0) | 2024.02.06 |
2024.02.01 내일배움캠프 29일차 TIL_Unity (숙련, 알고리즘) (0) | 2024.02.01 |
2024.01.30 내일배움캠프 27일차 TIL_Unity (입문, 알고리즘) (0) | 2024.01.30 |
2024.01.29 내일배움캠프 26일차 TIL_Unity (입문, 알고리즘) (0) | 2024.01.29 |