

'Unity > 셰이더 그래프' 카테고리의 다른 글
| Unity :: 셰이더 그래프 - 안개 열림/닫힘 이펙트 효과 (0) | 2025.03.11 |
|---|---|
| Unity :: 셰이더 그래프 - 슬라이드 다이아몬드 패턴 이펙트 (0) | 2025.03.11 |
| Unity :: 셰이더 그래프 - 4등분 십자가 열림/닫힘 이펙트 + 2D 도트 느낌 (0) | 2025.03.11 |


| Unity :: 셰이더 그래프 - 안개 열림/닫힘 이펙트 효과 (0) | 2025.03.11 |
|---|---|
| Unity :: 셰이더 그래프 - 슬라이드 다이아몬드 패턴 이펙트 (0) | 2025.03.11 |
| Unity :: 셰이더 그래프 - 4등분 십자가 열림/닫힘 이펙트 + 2D 도트 느낌 (0) | 2025.03.11 |
HLSL(High Level Shader Language) 코드 작성 없이 노드 기반으로 셰이더를 만들수 있는 기능입니다.

1. Project 부분에서 해당 경로를 따라가서 셰이더 그래프를 만들 수 있다.

2.우클릭 - Create Node를 사용하여 노드를 만들고 해당 Input에 기능들을 넣어 셰이더를 만들수 있다.

3.생성한 셰이더 그래프로 Material를 생성한다.


4.해당 Material를 사용할 스크립트 코드 작성
//Scene 전환시 사용되는 이펙트 효과로 간단하게 만든 스크립트 입니다.
//나중에 사용할시 Material 호출하여 사용하면 됨 .
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class TransitionScreen : MonoBehaviour
{
[SerializeField] private Material screenTransitionMaterial;
[SerializeField] private float transitionTime = 1f;
[SerializeField] private string prppertyName = "_Scrool";
public UnityAction OnTransitonDone;
public void OnTransitionScreen()
{
StartCoroutine(TransitionCoroutine());
}
private void Start()
{
StartCoroutine(TransitionCoroutine());
}
private IEnumerator TransitionCoroutine()
{
float curretnTime = 0;
while (curretnTime < transitionTime)
{
curretnTime += Time.deltaTime;
screenTransitionMaterial.SetFloat(prppertyName, Mathf.Lerp(0f, transitionTime, curretnTime));
yield return null;
}
OnTransitonDone?.Invoke();
}
}
간단하게 씬 전환시 사용되는 이펙트를 만들기위해 스크립트를 만들어 보았다.
5.Unity Scene에 오브젝트 및 컴포넌트 생성

Material을 잘 적용했는지 체크 할 것
6.체크

이번 포트폴리오 중 대화시스템을 구현 중에 화면 전환이 필요해서 셰이더 그래프를 익혀보았고
다른 예제들을 찾아보며 적용 중이다.
A.우선 Vector2 -> Vector3로 바뀌는 정도가 있긴하지만
이동은 x축과 z축으로 이동하기에 비슷하게 동작한다.
내 개인 얘기가 들어가기에 이 질문을 적었다.
나는 보통 3D 프로젝트 개발로 캐릭터 이동 구현을 할때 InputManager와 비슷하게 구성을 했다.

InputActionMap에서도 Type을 value - Axis로 해서 축 데이터를 받아 사용을 했었다.
하지만 오늘 Unity3D 강의를 듣는 중 튜터님의 방식이 직관성도 좋고 쉬워보여서 이 방법을 적기 위해 적었다.


위의 방식으로 PlayerInput컴포넌트를 이용해서 이동을 제어하게 구현 하였다.
private Vector2 curMovementInput;
public void OnMove(InputAction.CallbackContext context)
{
//InputActionPhase : 해당 키의 입력 상태를 나타낸 열거형 변수
//키가 눌리고 있을때 해당 Input값을 Vector2로 변환하여 반환하고 있다.
if (context.phase == InputActionPhase.Performed)
{
curMovementInput = context.ReadValue<Vector2>();
}
//키를 손에서 땟을때 해당 Input값을 (0,0) 으로 초기화 하고있다.
else if (context.phase == InputActionPhase.Canceled)
{
curMovementInput = Vector2.zero;
}
}
OnMove 함수에서 주의 깊게 볼건 InputActionPhase 라는 enum형 변수이다.

보통 나는 해당 키 상태를 하나하나 메서드로 나눠서 event 형태로 사용했었다.(그 방법밖에 몰랐기 때문에)
p.s Event 형태로 사용하는 InputSystem 예제
using UnityEngine;
using UnityEngine.InputSystem;
public class ActionMapSwitcher : MonoBehaviour
{
// InputActionAsset은 Unity의 Input Actions Asset 파일을 연결할 때 사용됩니다.
public InputActionAsset inputActions;
// Action Maps
private InputActionMap playerActionMap;
private void Awake()
{
// InputActionAsset에서 각 Action Map을 가져옴
playerActionMap = inputActions.FindActionMap("Player");
// Player Action Map에서 'Move' 액션을 가져와 이벤트 등록
InputAction moveAction = playerActionMap.FindAction("Move");
moveAction.started += OnMoveStarted;
moveAction.performed += OnMovePerformed;
moveAction.canceled += OnMoveCanceled;
}
private void OnEnable()
{
// 기본적으로 Player Action Map 활성화
playerActionMap.Enable();
}
private void OnDisable()
{
// 비활성화 시 모든 액션맵을 비활성화
playerActionMap.Disable();
}
// 'Move' 액션 관련 콜백 함수들
private void OnMoveStarted(InputAction.CallbackContext context)
{
Debug.Log("Move started");
}
private void OnMovePerformed(InputAction.CallbackContext context)
{
Vector2 moveInput = context.ReadValue<Vector2>();
Debug.Log($"Move performed: {moveInput}");
}
private void OnMoveCanceled(InputAction.CallbackContext context)
{
Debug.Log("Move canceled");
}
}
사실 해당 코드는 비활성화 되거나 파괴될때 event에 등록된 메서드들을 제외해야되는데
해당 코드가 없어 좋지 않은 코드다.
하지만 프로젝트 규모가 크지 않거나 간단한거면 InputActionPhase 를 이용하면 훨씬 가독성이 좋다는것을 느꼇기에 글을 적어보았다.
나는 오브젝트를 따라다니는 카메라를 만들거나 쳐다보는 카메라를 만들때 Cinemachine을 자주 사용한다.
하지만 시네머신을 활용하지 않고 직접 구현을 해봄으로 유니티엔진의 좌표계를 이해하려고 한다.


Unity3D에서는 왼손 좌표계를 사용한다.
D3D(DirectX3D)에서 사용되는 좌표계라고 생각하면된다. OpneGL은 오른손 좌표계를 사용한다.
왼손의 엄지가 축방향이라고 가정할때 말아쥔 손가락이 회전방향(Inspector에 양수를 적용시키면 적용되는 회전방향)을 의미한다.
Q.그럼 이 좌표계가 무슨 의미가 있어?
A. 오브젝트의 이동에따라 카메라가 회전할때 이 축방향을 정보로 회전하기 때문이다.
캐릭터의 시야가 좌우로 이동시 카메라는 Y축 회전을 해야되고
캐릭터의 시야가 위아래로 이동시 카메라는 X축 회전을 해야된다.
우선 마우스에 의해 캐릭터의 회전(시야)를 조절하기 위해 InputAction을 통해 키 바인딩을 한다.

Delta값은 컴퓨터의 성능에 따라 동작이 다르게 보이는것을 방지하기 위해 Time.deltaTime 사용했을때 봤을것이다.
즉 , Mouse의 Delta는 두 프레임 사이에 마우스가 이동한 < 변화량 >으로 이해하면된다.
변화량이라고 어필하는 이유는 가끔 이것을 좌표값이나 위치의 데이터 값으로 이해 할 수도 있어서 그렇다.
그럼 이 Input값을 통해서 우리는 마우스가 이동한 변화량을 반환 받아 카메라 회전에 사용 할 수 있다.
[Header("Look")] //카메라 회전 관련 필드
public Transform cameraContainer; //플레이어 자식 오브젝트의 메인카메라를 저장할 변수
public float minXLook; //x의 회전범위 최솟값
public float maxXLook; //x의 회전범위 최대값
private float camCurXRot; //현재 카메라의 X축 각도
public float lookSensitivy; //카메라 민감도
private Vector2 mouseDelta;//마우스 델타값을 저장할 변수
void CameraLook()
{
//위 아래 카메라 회전
//mouseDelta : 두 프레임 사이의 마우스가 이동한 <변화량>을 Vector2로 반환받음
//카메라 위,아래 회전시 X축이 회전 되야함 -> Mouse.delta는 Vector2로 x,y 이동한 변화량을 반환
//위 아래 회전시 X축으로 회전 , 2D에서 위,아래 관련 이동 데이터는 y축에 있기에
//회전 각도로 사용하려면 Delta.y값을 사용 해야한다.
camCurXRot += mouseDelta.y * lookSensitivy;
camCurXRot = Mathf.Clamp(camCurXRot, minXLook, maxXLook);
//유니티는 왼손 좌표계이기에 x축의 정회전방향은 아래(아래로 회전시 양수)이다.
//즉, 반대로 움직이기 때문에 -를 곱해서 정상적으로 움직이게 구현한것
cameraContainer.localEulerAngles = new Vector3(-camCurXRot, 0, 0);
//좌 우 카메라 회전
transform.eulerAngles += new Vector3(0, mouseDelta.x * lookSensitivy, 0);
}
위,아래 회전은 cameraContatiner를 회전하였고 좌,우 회전은 오브젝트 자체를 회전했다.
이것도 중요한 내용이다, 3D 게임에서 만약 위아래 회전을 카메라가 아닌 오브젝트에 주게 된다면
카메라가 위 아래로 이동할때마다 오브젝트 미친듯이 회전될거다.


이러한 현상 때문에 시야를 위,아래로 회전시키는 x축 회전을 카메라 에서 동작하게 한 것이고
좌,우 회전은 오브젝트가 그방향으로 바라볼때 몸도 그 방향으로 움직이는게 자연스럽기에 직접 회전을 시킨 것이다.

| Unity3D :: 발라트로 카드 연출 , 코드리뷰 (0) | 2025.11.04 |
|---|---|
| Unity3D :: Ray,RayCast,RayCastHit (0) | 2024.10.24 |
| Unity3D :: Skybox에 대해서 (0) | 2024.10.24 |
Unity :: 비트연산자와 레이어마스크
Q.비트연산자는 뭐야?A.컴퓨터가 나타내는 제일 작은 단위인 비트(bit = 0 또는 1)비트 연산자는 bit(0,1)을 이동하거나 논리 연산을 할떄 사용하는 것이다.논린 연산을 사용하면 이런식의 결과값을
01149.tistory.com
RayCast를 이용하여 충돌체크시 레이어를 사용하여 최적화 및 가독성을 올릴 수있다.
위에 참고한글은 Unity2D,3D 가릴것 없이 RayCast를 사용하여 레이어를 기준으로 충돌 처리를 적용하는 글이다.
나중에 찾아보게 될때 연관이 있어 링크를 달아놨다.

A.
Ray : 레이저 총 쏠때 그 레이저를 의미하며 , Ray라는 자료형 타입을 이용하여 원하는 방향으로 쏠 수있다.

origin은 레이저의 시작점 , direction은 레이저가 발사되는 방향을 의미한다.
Ray ray = new Ray(transfrom.position,transform.forward); //오브젝트에서 발사
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f,0.5f,0)); //카메라 중심에서 발사
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); //마우스에서 발사


위의 예제로 적은 Camera.main 메서드들은 전부 Ray를 반환하고 있다.
RayCast : 눈에 보이지 않는 레이저(Ray)에 맞은 오브젝트가 무엇인지 판단할때 사용되는 메서드이다.

RayCast는 Physics 포함되어있는 메서드이며 함수오버로딩도 15개나 있는 메서드이다.
//지상에 붙어있는지 확인하는 메서드
bool IsGrounded()
{
//오브젝트를 기준으로 동,서,남,북 방향에서 아랫방향으로 Ray를 발사하는 코드
Ray[] rays = new Ray[4]
{
new Ray(transform.position + (transform.forward * 0.2f) + (transform.up *0.01f), Vector3.down),
new Ray(transform.position + (-transform.forward * 0.2f) + (transform.up *0.01f), Vector3.down),
new Ray(transform.position + (transform.right * 0.2f) + (transform.up *0.01f), Vector3.down),
new Ray(transform.position + (-transform.forward * 0.2f) + (transform.up *0.01f), Vector3.down),
};
//발사된 4개의 Ray를 반복문으로 체크하여 조사
for (int i = 0; i < rays.Length; i++)
{
//Physics.Raycast(탐색하고 싶은 Ray,Ray의 길이,해당 Ray와 충돌시 비교할 레이어마스크)
if (Physics.Raycast(rays[i], 0.1f, groundLayerMask))
{
return true;
}
}
return false;
}

해당 예제 코드는 점프할때 캐릭터가 지상에 붙어있는지 체크하는 메서드이며 동,서,남,북으로 아랫방향으로 Ray를 쏴서
하나라도 Player를 제외한 레이어와 Ray가 충돌시 점프 가능이라고 true를 반환하는 메서드이다.
p.s 레이어마스크를 Inspector로 간단하게 설정하기
위에 참고글을 사용하면 스크립트로도 레이어의 충돌 체크 유무 판단을 내릴 수 있다.
하지만 Inspector로도 간단하게 되기에 적어보았다.
예시) 점프시에 자기 자신 레이어와 겹쳐서 점프가 무조건 된다는 판단을 내리면 안됨
Player 레이어를 제외하고 다른 레이어와 충돌시 점프가 가능하다고 판단


이렇게도 설정이 가능하다.
해당 밑에 글을 참고하면 더욱 쉽게 Raycast와 LayerMask를 쉽게 사용 할 수 있을것이다.
https://dallcom-forever2620.tistory.com/18
[Unity] Raycast Layermask 설정
Raycast 를 사용하여 타겟에게 ray 를 쏴서 처리하고 있을때 자신과 타겟사이에 오브젝트가 끼어들면 ray를 쏘지 못하게 되죠. 당연한 말이지만, raycast 사용중 자신과 타겟사이에 오브젝트가 끼어들
dallcom-forever2620.tistory.com
RayCastHit : Physics.RayCast() 메서드를 사용하여 Ray에 검출된 오브젝트의 충돌 정보만 아닌 충돌된 오브젝트의 정보가 필요할때 사용되는 [ 구조체 ]이다.

Ray ray;
RayCastHit hit;
void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
//true 면 RaycastHit에 데이터를 가지고 나옴
if(Physics.Raycast(ray,out hit))
{
Debug.Log("hit.distance"); //Ray의 원점에서 충돌한 객체와의 거리
Debug.Log("hit.point"); //RayCas가 감지된 위치
Debug.Log("hit.transform"); // 충돌객체의 transform에 대한 참조
//충돌한 객체의 콜라이더 컴포넌트에 접근하여 이름 호출
Debug.Log("hit.collider.gameObject.name");
}
}

| Unity3D :: 발라트로 카드 연출 , 코드리뷰 (0) | 2025.11.04 |
|---|---|
| Unity3D :: 3D월드에서 InputSystem을 사용하여 캐릭터 이동 + 카메라 회전 , enum InputActionPhase (0) | 2024.10.25 |
| Unity3D :: Skybox에 대해서 (0) | 2024.10.24 |
A. Unity 내에서 제공하는 물리연산 컴포넌트이다.
A.Rigidbody가 적용된 오브젝트에 AddForce 메서드를 사용하면 외부에서 물리적인 힘을 가하는 물리현상을 나타낼때 사용한다.
A.코드는 기본적으로 이런식으로 쓴다.

private Rigidbody _rigidbody;
private void Awake()
{
_rigidbody = GetComponent<Rigidbody>(); //오브젝트에 있는 Rigidbody 컴포넌트 호출
}
private void OnJump()
{
//rigidbody컴포넌트에서 AddForce() 메서드를 호출하여 사용
_rigidbody.AddForce(Vector2.up * jumpPower, ForceMode.Impulse);
}
AddForce() 인자값으로 ForceMode라는 enum 값이 아래와 같이 들어가게된다.
아래의 코드는 유니티 엔진 내부 코드이다.

| ForceMode Type | 설명 |
| Force | 힘을 지속적으로 적용할때 사용됨 |
| Acceleration | 가속도를 적용할떄 사용되며, 이전 힘의 누적에 따라서 점진적으로 더 빠르게 움직이게 됨 |
| Impulse | 순간적인 힘을 적용하여, 짧은시간에 빠른 움직임이 필요할때 사용 |
| VelocityChange | 변화하는 속도를 적용, 오브젝트의 현재 속도를 변경하면서 사용될때 사용됨 |
| Cinemachine - VirtualCamera , Animatior Controller 기록용 (0) | 2026.03.14 |
|---|---|
| Unity :: 셰이더 그래프 (0) | 2025.03.11 |
| Unity :: UnityEngine에서 제공하는 Pool 패키지(오브젝트 풀) (0) | 2024.10.23 |
| Unity :: (2024.10.21수정)제네릭 클래스를 상속받은 Class는 오브젝트 생성 및 컴포넌트로 사용 할수 잇지만 제네릭 클래스 그 자체는 사용 할 수 없다. (0) | 2024.10.21 |
| Unity :: TMP(Text Mesh Pro) 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
A.월드스페이스의 배경을 둘러싸는 환경 매핑 기술 이다.
Unity에서는 Scene의 BackGround로 주로 사용되며 보통 자연적인 환경(하늘,구름,산)을 표현할때 많이 사용
미리 구성된 스카이박스를 가져와서 사용 할수 있어 Asset으로도 활용도가 높음
이 SkyBox를 동적으로 변경하여 낮과 밤 등의 시간대나 특정 이벤트 연출을 줄 수있지만
단점으로는 아무래도 텍스쳐로 맵핑하는 그래픽렌더링이 들어가니 최적화는 좋지 않다.
A.SkyBox는 Material로 구성되어있으면 Material의 Shader를 변경하여 사용하면된다.


어떤 Type을 선택하든 공통적으로 Tint Color(Procedural은 Sky와 Ground 2개로 설정가능) , Exposure를 제어 할 수 있다.
| 기능 이름 | 설명 |
| Tint Color | Skybox의 색상을 결정 합니다. |
| Exposure | 스카이박스의 밝기를 조정합니다. |
Skybox를 선택하면 4가지 타입에 대한 설명입니다.
| Skybox의 Type | 설명 |
| 6-Sided | 여섯개의 텍스처를 사용하여 위,아래,왼쪽,오른쪽,앞,뒤에 배치하여 사용됩니다. 하지만 이 Type의 단점은 6면의 리소스(이미지)를 전부 구해야하니 관리 측면에서는 힘들수가 있다. |
| CubeMap | 여섯개의 텍스처를 사용하여 위,아래,왼쪽,오른쪽,앞,뒤에 배치하여 사용됩니다. 그대신 하나의 리소스(이미지)로 6면을 전부 맵핑 할 수 있습니다. |
| Panoramic(파노라마) | 파노라마가 구체형 스카이박스로 리소스(이미지)를 구체형으로 맵핑하여 사용 할 수있습니다. 360도(수평) ,180도(수직) 이 두종류중 하나를 골라 사용합니다. |
| Procedural(절차적) | 미리 정의된 텍스처가 아닌 유니티의 절차적 알고리즘을 통해 하늘을 동적으로 생성하는 방식으로 시간의 흐름을 나타내기 좋습니다. 하늘의 색상,태양 및 달의 위치, 대기현상 , 낮과 밤 등 다양한 시간적 흐름 연출을 나타낼 수 있습니다. |
Q.Skybox Material도 만들고 Shader도 선택해서 inspector에 속성값도 다 조절했어 어떡해 적용해야돼?
A. Window - Rendering - Lighting → Lighting(Environment) → Material을 변경하면 적용 됩니다.


| Unity3D :: 발라트로 카드 연출 , 코드리뷰 (0) | 2025.11.04 |
|---|---|
| Unity3D :: 3D월드에서 InputSystem을 사용하여 캐릭터 이동 + 카메라 회전 , enum InputActionPhase (0) | 2024.10.25 |
| Unity3D :: Ray,RayCast,RayCastHit (0) | 2024.10.24 |
게임 개발을 공부하면 오브젝트 풀에 대해 배우면서
오브젝트를 미리 생성하고 필요할때 꺼내서 사용하고 사용이 다되면 풀에 반납하여 비활성화 시켜주는 것을
오브젝트 풀링이라고 배워왔다.
하지만 유니티에서는 이 오브젝트 풀을 사용 할수 있게 패키지로 제공하고 있다.
using UnityEngine.Pool;
해당 패키지를 사용하기 위해서는 해당 코드를 작성하고 사용해야된다.
해당 Pool를 사용하려면 어떡해 해야되는가?
public IObjectPool<GameObject> objectPool;
public ObjectPool<GameObject> pool;
변수로 선언할때는 이 두방식을 이용하여 변수를 초기화 하여 사용하면된다.

pool = new ObjectPool<GameObject>(CreateObject, GetObject, ReleaseObject, DestroyObject, collectionChecks, minSize, maxSize);
objectPool = new ObjectPool<GameObject>(CreateObject, GetObject, ReleaseObject, DestroyObject, collectionChecks, minSize, maxSize);
이런식으로 선언을 하면된다.
namespace UnityEngine.Pool
{
public interface IObjectPool<T> where T : class
{
int CountInactive { get; }
T Get();
PooledObject<T> Get(out T v);
void Release(T element);
void Clear();
}
}
해당 코드가 IObjectPool의 내부 구조이다.
using System.Collections.Generic;
using System.ComponentModel;
using UnityEditor.Presets;
using UnityEngine;
using UnityEngine.Pool;
//최소 50개의 오브젝트 수 보장, 부족할 경우 누적 300개까지 추가 생성, 300개가 넘어갈 경우 가장 오래전에 생성된 오브젝트를 반환 후 재사용
public class Week2_OjbectPool_Q4 : Singleton<Week2_OjbectPool_Q4>
{
[SerializeField] private GameObject prefab;
public ObjectPool<GameObject> pool;
public bool collectionChecks = true;
private const int minSize = 50;
private const int maxSize = 300;
private GameObject container;
void Awake()
{
container = new GameObject(prefab.name + "_Container");
/*
createFunc: 오브젝트 생성 함수 (Func)
actionOnGet: 풀에서 오브젝트를 가져오는 함수 (Action)
actionOnRelease: 오브젝트를 비활성화할 때 호출하는 함수 (Action)
actionOnDestroy: 오브젝트 파괴 함수 (Action)
collectionCheck: 중복 반환 체크 (bool)
defaultCapacity: ObjectPool의 List<T>에 미리 자리 만드는것(오브젝트 생성x)(int)
maxSize: 저장할 오브젝트의 최대 갯수 (int)
*/
pool = new ObjectPool<GameObject>(CreateObject, GetObject, ReleaseObject, DestroyObject, collectionChecks, minSize, maxSize);
}
private GameObject CreateObject()
{
// [요구스펙 1] Create Object
//Instantiate();
GameObject obj = Instantiate(prefab, container.transform);
return obj;
}
public void GetObject(GameObject obj)
{
// [요구스펙 2] Get Object
obj.gameObject.SetActive(true);
}
public void ReleaseObject(GameObject obj)
{
// [요구스펙 3] Release Object
obj.gameObject.SetActive(false);
}
public void DestroyObject(GameObject obj)
{
//오브젝트 파괴 함수
Destroy(obj.gameObject);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
for (int i = 0; i < 10; i++)
{
pool.Get();
}
}
}
}
해당 코드는 UnityEngine.Pool을 이용하여 오브젝트 풀을 구성한 예제 코드이다.
사용시에는 따로 풀링할 오브젝트를 넣어 등록해서 사용해야된다.
해당 Docs를 참고하여 글을 작성하였습니다.
https://docs.unity3d.com/ScriptReference/Pool.ObjectPool_1.html
Unity - Scripting API: ObjectPool<T0>
Object Pooling is a way to optimize your projects and lower the burden that is placed on the CPU when having to rapidly create and destroy new objects. It is a good practice and design pattern to keep in mind to help relieve the processing power of the CPU
docs.unity3d.com
| Unity :: 셰이더 그래프 (0) | 2025.03.11 |
|---|---|
| Unity :: Rigidbody컴포넌트의 Rigidbody.AddForce() , ForceMode (0) | 2024.10.24 |
| Unity :: (2024.10.21수정)제네릭 클래스를 상속받은 Class는 오브젝트 생성 및 컴포넌트로 사용 할수 잇지만 제네릭 클래스 그 자체는 사용 할 수 없다. (0) | 2024.10.21 |
| Unity :: TMP(Text Mesh Pro) 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
| Unity :: 비트연산자와 레이어마스크 (0) | 2024.10.14 |
오브젝트 풀링 만들려고 구조 잡는중에
ObjectPool을 제네릭으로 만들고 게임오브젝트 생성하듯이 하려고했으나
자꾸 null값을 반환하여 왜그런지 찾아보니
제네릭 클래스는 컴포넌트화하지 못한다 , 즉, 오브젝트로 못만든다는 뜻이다.
그래서 Monobehaviour를 해지하고 C#문법을 이용하여 Class를 호출하여 사용하여아한다.
public class ObjectPool<T> : MonoBehaviour where T : Component
{
public Queue<T> PoolQueue;
public void Start()
{
PoolQueue = new Queue<T>();
}
public void Initailize(int poolCount, T poolObject)
{
GameObject poolContainer = new GameObject("Pool_Container_" + poolObject.name);
T gameObj;
for (int i = 0; i < poolCount; i++)
{
gameObj = Instantiate(poolObject, poolContainer.transform);
gameObj.gameObject.SetActive(false);
PoolQueue.Enqueue(gameObj);
}
}
}
/*====================================================================*/
public class EnemySpawnManager : SpawnManager<TestMonster>
{
private void Start()
{
foreach (TestMonster prefab in prefabesList)
{
prefab.OnEventPushObject += PushObject;
//트러블슈팅이 난구간 objectPool을 자꾸 null을 반환한다.
ObjectPool<TestMonster> objectPool = new ObjectPool<TestMonster>();
objectPool.Initailize(prefab.PoolCount, prefab);
objectPools.Add(prefab.name, objectPool);
}
Initialize();
}
}
해당 오브젝트의 objectPool을 받아오려 했으나 자꾸 null을 반환해서 문제가 발생하였다.
//트러블슈팅 대처 : Mononehaviour 를 상속해지하였음
public class ObjectPool<T> where T : MonoBehaviour
{
public Queue<T> PoolQueue = new Queue<T>();
public Queue<T> PoolQueue = new Queue<T>();
//Initialize 메서드를 변경하였음 (트러블슈팅과 문제되는부분 x)
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 class EnemySpawnManager : SpawnManager<TestMonster>
{
private void Awake()
{
TestMonster gameObj;
foreach (TestMonster prefab in prefabesList)
{
GameObject poolContainer = new GameObject("Pool_Container_" + prefab.name);
//트러블슈팅 대처 :
//Monobehaviour를 상속해지해서 new 어트리뷰트를 이용해여 클래스 객체 생성을 함
ObjectPool<TestMonster> objectPool = new ObjectPool<TestMonster>();
for (int i = 0; i < prefab.PoolCount; i++)
{
gameObj = Instantiate(prefab, poolContainer.transform);
gameObj.OnEventPushObject += PushObject;
objectPool.InitPushObject(gameObj);
}
objectPools.Add(prefab.monsterName, objectPool);
}
Initialize();
}
}
ObjectPool의 Monobehaviour를 상속해지하고 C# 문법의 new로 객체를 생성한뒤 호출하여 사용하였다.
=============================2024.10.21 수정=============================================
제네릭을 상속 받은 클래스들 -> EnemySpawnManager는 이미 오브젝트로 만들어 진다.
하지만 ObjectPool<T>를 컴포넌트 및 오브젝트화해서 사용하지 못한다.
| Unity :: Rigidbody컴포넌트의 Rigidbody.AddForce() , ForceMode (0) | 2024.10.24 |
|---|---|
| Unity :: UnityEngine에서 제공하는 Pool 패키지(오브젝트 풀) (0) | 2024.10.23 |
| Unity :: TMP(Text Mesh Pro) 한글 폰트로 쓰기 , 스크립트에서 사용하기 (0) | 2024.10.15 |
| Unity :: 비트연산자와 레이어마스크 (0) | 2024.10.14 |
| Unity :: StringToHash 메서드 사용하기(애니메이터 컨트롤러) (0) | 2024.10.14 |