어제 구현한 생선들을 Object Pool에 넣어 관리해주고 싶어 Object Pool에 대해 다시 알아봤다.

에셋 입힌 생선들

 

Object Pool 구현

첫 번째 방법

https://www.youtube.com/watch?v=JxP-kqstMAY&ab_channel=%EB%B2%A0%EB%A5%B4%EC%9D%98%EA%B2%8C%EC%9E%84%EA%B0%9C%EB%B0%9C%EC%9C%A0%ED%8A%9C%EB%B8%8C

이 사람의 코드를 보고 따라해봤다.

이 코드는 미리 Instantiate를 하지 않고, 필요할 때마다 maxSize까지 생성을 한다.

Instantiate된 게임오브젝트는 Destroy되지 않고 특정 조건에 비활성화, 활성화하는 풀 방식이다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;

public class FishCreater : MonoBehaviour
{
    [SerializeField] private GameObject _fishPrefab;
    [SerializeField] private float _createFishTime = 1f;

    private IObjectPool<FishObstacle> _pool;

    private void Awake()
    {
        _pool = new ObjectPool<FishObstacle>(CreateFish, OnGetFish, OnReleaseFish, OnDestroyFish, maxSize: 40);
    }

    private void Start()
    {
        StartCoroutine(GetFish());
    }

    IEnumerator GetFish()
    {
        while (true)
        {
            FishObstacle fish = _pool.Get();
            fish.transform.position = Vector3.up;
            yield return new WaitForSeconds(_createFishTime);
        }
    }

    private FishObstacle CreateFish()
    {
        FishObstacle fish = Instantiate(_fishPrefab).GetComponent<FishObstacle>();
        fish.SetManagedPool(_pool);
        fish.transform.SetParent(transform);
        return fish;
    }

    private void OnGetFish(FishObstacle fish)
    {
        fish.gameObject.SetActive(true);
    }

    private void OnReleaseFish(FishObstacle fish)
    {
        fish.gameObject.SetActive(false);
    }

    private void OnDestroyFish(FishObstacle fish)
    {
        Destroy(fish.gameObject);
    }
}

 

 

구현을 하고 나니 풀 생성 후 풀에 Instantiate를 한 번에 20개씩 해주고 거기서 가져다 쓰는 방식을 써보고 싶어졌다.

 

 

두 번째 방법

https://learn.unity.com/tutorial/introduction-to-object-pooling#

유니티 공식 튜토리얼의 방식

 

 public static ObjectPool SharedInstance;
 public List<GameObject> PooledObjects;
 public GameObject ObjectToPool;
 public int AmountToPool;

 void Awake()
 {
     SharedInstance = this;
 }

 private void Start()
 {
     PooledObjects = new List<GameObject>();
     GameObject tmp;
     for(int i = 0; i < AmountToPool; ++i)
     {
         tmp = Instantiate(ObjectToPool);
         tmp.SetActive(false);
         PooledObjects.Add(tmp);
     }
 }

 

 

플레이어를 튕겨내는 Object

 

방향벡터 구하기 : 목표position (충돌 지점) - 시작 position (Player)

Vector3 collisionDirection = collision.contacts[0].point - collision.gameObject.transform.position;

 

collision.contacts[0].normal: 충돌 지점의 법선 벡터

 

Vector3.Reflect

inDirection: 들어오는 벡터의 방향

inNormal: 입력 벡터가 반사될 표면의 법선 벡터

반환값: 반사된 벡터

 

 

플레이어에 래그돌 적용

 

 

래그돌을 적용할 땐 애니메이터를 꺼줘야한다.

래그돌 적용된 캐릭터

 

플레이어가 피격되었을 때 래그돌 상태가 되도록 코드를 짜줘야한다.

 

 

+ 플레이어의 x축 z축으로 AddForce가 안되는 문제 해결중......