오브젝트 조작 및 카메라 회전을 이해하기 위해 작성하였고
예전에 작성하던 제 스타일하고 달라서 나중에 필요할때 보려고 TIL로 작성하였습니다.
오브젝트 조작 및 카메라 회전을 이해하기 위해 작성하였고
예전에 작성하던 제 스타일하고 달라서 나중에 필요할때 보려고 TIL로 작성하였습니다.
TIL : 2024-10-28(월) :: RigidBody.velocity 및 RigidBody.AddForce를 이용한 물리계산시 Time.deltaTime 및 Time.FixeddeltaTime을 연산하지 않는것이 좋다. (0) | 2024.10.28 |
---|---|
TIL : 2024-10-25(금) :: Unity3D에서 InputSystem을 사용하여 캐릭터 이동 및 카메라 회전 제어하기 (0) | 2024.10.25 |
TIL : 2024-10-23(수) :: UnityEngine.Pool 사용하기 (0) | 2024.10.23 |
TIL : 2024-10-22(화) :: 설계하며 생각하기 (0) | 2024.10.22 |
TIL : 2024-10-21(월) :: 제네릭을 사용하는 의미 (0) | 2024.10.21 |
TIL : 2024-10-25(금) :: Unity3D에서 InputSystem을 사용하여 캐릭터 이동 및 카메라 회전 제어하기 (0) | 2024.10.25 |
---|---|
TIL : 2024-10-24(목) :: SkyBox,Rigidbody.AddForce(),Ray 사용하는 방법 (0) | 2024.10.24 |
TIL : 2024-10-22(화) :: 설계하며 생각하기 (0) | 2024.10.22 |
TIL : 2024-10-21(월) :: 제네릭을 사용하는 의미 (0) | 2024.10.21 |
TIL : 2024-10-18(금) :: 외부에서 데이터를 불러오는 전략(개인생각 정리) (0) | 2024.10.18 |
오늘 유니티 2D 팀프로젝트 하고 튜터님들이 각 팀들마다 피드백 해주셨는데
내 설계에도 도움이 될것 같아서 작성해본다.
0.프리팹화 한거 Resources를 사용하여 동적 생성하여 Scene 채우기 할것
1.매니저에 다 모든 기능을 넣지마라
2.Find 메서들 지양해라
3.문자열을 사용하는 메서드들을 해쉬코드로 변경하여 사용할것
4.오브젝트 충돌 검사시 태그 검사가 아닌
오브젝트 비트연산자 + 레이어마스크 검사를 하거나
컴포넌트를 호출하여 검사하도록 하자
5.이름이니셜로 폴더링 하지말것, 만약 그 팀원 퇴사했다 치면
어떤 기능일 구현했는지 모르기 때문에 매우 큰 문제가 된다.결국 코드 작업시 남의 스크립트 영역에 침범하게 될일이 있으므로 기능 별로 폴더링하여 사용하여야된다.
6.게임매니저가 Player를 찾게 하지말고
Player에서 게임매니저를 접근하게 하는 로직을 생성하자
ex)Player 오브젝트에서 게임 저장
GameManager.Instance.GameSave() ....
7.매직 넘버 지양하자
코드에 하드코딩으로 숫자 집어넣는거
8.파입 입출력을 이용하자 스테이지 구성을 지향하자
9.프로젝트 진행할때 플랫폼 설정하기-> 안드로이드,IOS,윈도우 등등...
10.프로젝트 세팅에서 fixedUpdate의 시간을 조정 가능하다.
11.GetComponent<>는 최적화가 잘되어있지만 수시로 불러 사용하는건 지양해야된다.
12.Dirctinoray의 키값을 enum으로 해서 가독성을 올릴것
13.코루틴은 효과만 관리하고 플래그(변수)는 메서드에서 관리하는것이 좋다.
14.코루틴이 실행중인데 중복 실행 방지 로직은 항상 생각할것
15.어디서든 UI매니저를 통해서 호출하게하면 좋다.
각팀들에게 해주셨던 피드백을 간단하게 정리한 내용이다.
설계할때 한번씩 보고 설계하도록 하자
TIL : 2024-10-24(목) :: SkyBox,Rigidbody.AddForce(),Ray 사용하는 방법 (0) | 2024.10.24 |
---|---|
TIL : 2024-10-23(수) :: UnityEngine.Pool 사용하기 (0) | 2024.10.23 |
TIL : 2024-10-21(월) :: 제네릭을 사용하는 의미 (0) | 2024.10.21 |
TIL : 2024-10-18(금) :: 외부에서 데이터를 불러오는 전략(개인생각 정리) (0) | 2024.10.18 |
TIL : 2024-10-17(목) :: 벡터의 내적(Vector2.Dot) (0) | 2024.10.17 |
Q.제네릭을 왜 사용하는걸까?
A.간단히 말해서 클래스를 자료형에 상관없이 자유롭게 쓸 수 있게 하는것
즉, 클래스를 변수처럼 사용 하고 싶을때 주로 사용한다.
정수,문자열 데이터 를 담는공간을 변수라 하고
함수를 변수처럼 사용하면 delegate를 사용하고
class를 변수처럼 사용하기 위해 제네릭을 사용한다.
이런 느낌으로 보면 된다.
Q.제네릭을 쓰면 뭐가 좋아?
A. 클래스에 자료형 제약을 걸고 사용 하여 처음 구조 설계시 시간이 걸리지만
유지 보수에 매우 효율적이기 때문이다.
Q.어떨때 써??
A. 자주 사용되는 클래스인데 자료형이 다양한 클래스인경우에 주로 사용된다.
첫번쨰 예시 ) 탄막슈팅게임에서 총알,아이템,이펙트 등등 다양하게 객체를 생성해야 되는 류의 게임에서
오브젝트 풀링을 제너릭 구조로 설계해서 사용하기
자료형을 담을 오브젝트 Pool을 선언해 준다. 그리고 제약조건으로 MonoBehaviour를 선언하여 오브젝트 및 컴포넌트로 사용 할수 있는 class만 T로 선언 할 수있다.
public class ObjectPool<T> where T : MonoBehaviour
{
public Queue<T> PoolQueue = new Queue<T>();
public bool InitPushObject(T poolObject)
{
if (poolObject == null)
{
Debug.Log(poolObject.name + "이 null 입니다.");
return false;
}
poolObject.gameObject.SetActive(false);
PoolQueue.Enqueue(poolObject);
return true;
}
public T PoolObject(Vector2 pos)
{
if (PoolQueue.Count <= 5)
{
Debug.Log(typeof(T).Name + "오브젝트 갯수 부족!");
return null;
}
T obj = PoolQueue.Dequeue();
obj.gameObject.transform.position = pos;
obj.gameObject.SetActive(true);
return obj;
}
public void PushObject(T pushObj)
{
pushObj.gameObject.SetActive(false);
PoolQueue.Enqueue(pushObj);
//Debug.Log("총알 큐 갯수"+PoolQueue.Count);
}
}
T로 해당 자료형을 선언하고 Dictionary의 value 값으로 ObjectPool<T>를 선언하여
SpawnManager도 제네릭으로 설계한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public abstract class SpawnManager<T> : MonoBehaviour, iManager where T : MonoBehaviour,iPoolable<T>
{
//부모 클래스를 저장
[SerializeField] protected List<T> prefabesList;
protected Dictionary<string, ObjectPool<T>> objectPools = new Dictionary<string, ObjectPool<T>>();
public virtual void Initialize() { }
}
결국 최종적으로 사용하는 EnemySpanwManager에 SpawnManager<EnemyController>를 상속하여 제네릭으로 생성하였다. 이렇게되면 자료형만 바꿔 작성하면 Item,Effect 생상선이 올라가기 때문이다.
또한 이 구조에서 T는 부모 클래스를 넣고서 EnemyController의 자식 클래스로 형변환하여 확장성도 확보가 가능해진다.
public class EnemySpawnManager : SpawnManager<EnemyController>
{
[SerializeField] private ItemSpawnManager itemSpawnManager;
[SerializeField] private EffectManager effectManager;
public override void Initialize()
{
Debug.Log(gameObject.name + "Initalize 완료!");
}
private void Awake()
{
EnemyController gameObj;
foreach (EnemyController prefab in prefabesList)
{
GameObject poolContainer = new GameObject("Pool_Container_" + prefab.name);
ObjectPool<EnemyController> objectPool = new ObjectPool<EnemyController>();
for (int i = 0; i < prefab.EnemySO.PoolCount; i++)
{
gameObj = Instantiate(prefab, poolContainer.transform);
gameObj.OnEventDieObject += GameManager.Instance.GetScore;
gameObj.OnEventPushObject += PushObject;
gameObj.OnEventDropItem += itemSpawnManager.RandomPoolObject;
gameObj.OnEventDieEffectObject += effectManager.PoolObject;
objectPool.InitPushObject(gameObj);
}
objectPools.Add(prefab.EnemySO.enemyName, objectPool);
}
Initialize();
}
public EnemyController PoolObject(string objName, Vector2 spawnPos)
{
return objectPools[objName].PoolObject(spawnPos);
}
public EnemyController PoolObject(EnemyController enemy, Vector2 spawnPos)
{
return objectPools[enemy.EnemySO.enemyName].PoolObject(spawnPos);
}
private void PushObject(EnemyController enemy)
{
//objectPools[testmonster.monsterName].PushObject(testmonster);
objectPools[enemy.EnemySO.enemyName].PushObject(enemy);
}
}
예시2) 싱글톤 구조를 제네릭으로 구성
싱글톤 구조는 Manager 클래스에서 정말 많이 쓰이기에 제네릭으로 구조를 잡고 상속으로 사용하게되면
효율성이 매우증가한다.
이 외에도 많은 사용용도가 있지만 나는 이 목적으로 많이 사용을 했던것 같다.
TIL : 2024-10-23(수) :: UnityEngine.Pool 사용하기 (0) | 2024.10.23 |
---|---|
TIL : 2024-10-22(화) :: 설계하며 생각하기 (0) | 2024.10.22 |
TIL : 2024-10-18(금) :: 외부에서 데이터를 불러오는 전략(개인생각 정리) (0) | 2024.10.18 |
TIL : 2024-10-17(목) :: 벡터의 내적(Vector2.Dot) (0) | 2024.10.17 |
TIL : 2024-10-16(수) :: Lerp,Slerp 사용법 / 제네릭 클래스는 컴포넌트로 사용 할 수 없다. (0) | 2024.10.16 |
개발 도중 외부에서 접근해서 데이터나 객체를 가져와야되는 경우가 있는데
이렇게 될 경우 해당 매니저는 이 기능이 필요없는데 이 기능을 참조해서 가지고 있어야되는경우가 종종 생긴다.
ex) EnemyManager는 적만 관리/생성 하는 클래스인데 아이템드랍,적 파괴시 이펙트 효과 등 이벤트를 적용시키려다 보니 ItemManager와 EffectManager가 참조 되있는 경우
이런 경우를 대처하기위해 첫 설계를 잘해야되는데 어떡해 해야 되는가에 대한 정리이다.
해당 캠프 진행중 튜터님과의 면담으로 답변 받은것을 정리한 내용이다.
1.해당 Scene에서 사용되는 Data의 중간다리 역할을 해주는 Class를 만들어서 사용한다.
이 방법은 Scene 이동시에도 싱글톤 패턴을 사용하면 매우 효과적이며 의존관계가 아닌 연관관계로 멤버변수로 필요한 class들을 가지는 방법이다.
2.이 방법은 해당 기능을 따로 class로 만들고 데이터를 보관하고 있는 컨테이너 클래스로 만들어 필요할떄마다 해당 클래스를 호출하여 쓰는 방법이다. 예시로 SpawnManager로 객체들을 생성하는 기능을 하나의 Class로 만들고 오브젝트 관리하는 Class를 만들어 해당 Class에서는 오브젝트 풀링처럼 객체의 data(prefab)만 꺼내서 전달해주는 방식이다.
TIL : 2024-10-22(화) :: 설계하며 생각하기 (0) | 2024.10.22 |
---|---|
TIL : 2024-10-21(월) :: 제네릭을 사용하는 의미 (0) | 2024.10.21 |
TIL : 2024-10-17(목) :: 벡터의 내적(Vector2.Dot) (0) | 2024.10.17 |
TIL : 2024-10-16(수) :: Lerp,Slerp 사용법 / 제네릭 클래스는 컴포넌트로 사용 할 수 없다. (0) | 2024.10.16 |
TIL : 2024-10-15(화) :: TMP에서 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
벡터의 내적은 두 벡터사이의 각도를 알아낼때 주로 사용한다.
그렇다고 내적을 해서 나온값이 두 벡터사이의 각도값이 아니다.
벡터의 내적은 Dot Product라고도 불리며 두 벡터의 곱으로 스칼라 값을 가져올수 있고
해당 스칼라값을 ACos(theta)에 사용하면 두벡터의 사이각을 가져올 수있다.
Vector2.Dot()를 활용해보기 위해 간단한 예제 코드이다.
using UnityEngine;
public class VectorAngle : MonoBehaviour
{
public Vector2 v1 = new Vector2(1, 0);
public Vector2 v2 = new Vector2(0, 1);
void Start()
{
float dotProduct = Vector2.Dot(v1, v2);
// .magnitude : 해당 벡터의 스칼라값(크기)를 반환함
float magnitude1 = v1.magnitude;
float magnitude2 = v2.magnitude;
// dot내적값 = A크기 * B크기 * Cos(세타)
// Cos(세타) = dot 내적값 / A크기 * B크기 로 식변환
float cosAngle = dotProduct / (magnitude1 * magnitude2);
// 구한 각도값을 이용하여 Acos에 넣고 사용
float angleInRadians = Mathf.Acos(cosAngle);
//라다안으로 반환하기에 Rad2Deg 사용
float angleInDegrees = angleInRadians * Mathf.Rad2Deg;
}
}
이것으로 해당 벡터의 각도 값을 알아 낼 수 있다.
TIL : 2024-10-21(월) :: 제네릭을 사용하는 의미 (0) | 2024.10.21 |
---|---|
TIL : 2024-10-18(금) :: 외부에서 데이터를 불러오는 전략(개인생각 정리) (0) | 2024.10.18 |
TIL : 2024-10-16(수) :: Lerp,Slerp 사용법 / 제네릭 클래스는 컴포넌트로 사용 할 수 없다. (0) | 2024.10.16 |
TIL : 2024-10-15(화) :: TMP에서 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
TIL : 2024-10-14(월) :: C# 메모리구조 , 비트연산자와 레이어마스크 (0) | 2024.10.14 |
TIL : 2024-10-18(금) :: 외부에서 데이터를 불러오는 전략(개인생각 정리) (0) | 2024.10.18 |
---|---|
TIL : 2024-10-17(목) :: 벡터의 내적(Vector2.Dot) (0) | 2024.10.17 |
TIL : 2024-10-15(화) :: TMP에서 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
TIL : 2024-10-14(월) :: C# 메모리구조 , 비트연산자와 레이어마스크 (0) | 2024.10.14 |
TIL : 2024-10-11(금) :: 트러블슈팅 : 삭제된 객체에 접근하는 컴포넌트들 (0) | 2024.10.11 |