프로젝트/건즈앤 레이첼스

[유니티 프로젝트] 미니맵 기능 추가 및 필드 재화 & 에테르 재화 연출 및 획득 연출 & 인벤토리 아이템 획득 연출

Bueong_E 2023. 5. 21. 00:15
반응형
SMALL
  • 미니맵의 기능 추가
    • 터치시 큰 화면으로 전체적인 미니맵의 모습을 볼수 있다.
    • 다시 클릭시 원래 크기로 변경
    • 변경시 좀더 확대된 모습의 전체적인 미니맵의 모습을 볼수 있다.

코드

using DG.Tweening;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;

public class UIMiniMap : MonoBehaviour
{
    //빼야함
    public MapGenerator generator;
    //빼야함
    public DungeonSceneMain main;
    public Button btnMapReGen;
    public Text txtMapCount;
    public Button btnMaxRowPlus;
    public Button btnMaxRowMinus;
    public Button btnMaxColPlus;
    public Button btnMaxColMinus;
    public Text txtRowCol;

    public Camera miniMapCam;
    public GameObject imgCurrentMap;

    [SerializeField]
    private Minimap minimap;
    private RectTransform minimapRect;
    private CanvasGroup minimapCanvas;
    private Image minimapImage;
    private Vector2 minimapPos;
    private Vector3 minimapExpendScale;

    private bool isExpend;

    public void Init()
    {
        this.imgCurrentMap = Instantiate(this.imgCurrentMap);
        this.StartCoroutine(this.mapFlickerling());

        this.minimapRect = this.minimap.GetComponent<RectTransform>();
        this.minimapCanvas = this.minimap.GetComponent<CanvasGroup>();
        this.minimapImage = this.minimap.GetComponent<Image>();
        this.minimapPos = this.minimapRect.position;

        this.minimap.onTouched = () =>
        {
            this.DoExpend();
        };
        this.btnMapReGen.onClick.AddListener(() =>
        {
            this.main.InitStage();
            this.MiniMapUpdate(GameObject.FindGameObjectWithTag("Player").transform.position);
            //this.txtMapCount.text = string.Format("Map Count : {0}", this.generator.wholeRoomList.Count);
        });

        this.btnMaxRowPlus.onClick.AddListener(() =>
        {
            this.generator.maxRow++;
            this.txtRowCol.text = string.Format("MaxRow  : {0}\nMaxCol  : {1} ", this.generator.maxRow, this.generator.maxCol);
        });

        this.btnMaxRowMinus.onClick.AddListener(() =>
        {
            this.generator.maxRow--;
            this.txtRowCol.text = string.Format("MaxRow  : {0}\nMaxCol  : {1} ", this.generator.maxRow, this.generator.maxCol);
        });

        this.btnMaxColPlus.onClick.AddListener(() =>
        {
            this.generator.maxCol++;
            this.txtRowCol.text = string.Format("MaxRow  : {0}\nMaxCol  : {1} ", this.generator.maxRow, this.generator.maxCol);
        });

        this.btnMaxColMinus.onClick.AddListener(() =>
        {
            this.generator.maxCol--;
            this.txtRowCol.text = string.Format("MaxRow  : {0}\nMaxCol  : {1} ", this.generator.maxRow, this.generator.maxCol);
        });

        this.btnMapReGen.gameObject.SetActive(false);
        this.btnMaxRowPlus.gameObject.SetActive(false);
        this.btnMaxRowMinus.gameObject.SetActive(false);
        this.btnMaxColPlus.gameObject.SetActive(false);
        this.btnMaxColMinus.gameObject.SetActive(false);
        this.txtMapCount.gameObject.SetActive(false);
        this.txtRowCol.gameObject.SetActive(false);
    }

    public void MiniMapUpdate(Vector3 roomPos)
    {
        //미니맵 카메라 위치 조정
        this.miniMapCam.transform.position = new Vector3(roomPos.x, roomPos.y, -800f);
        this.imgCurrentMap.transform.position = new Vector3(roomPos.x, roomPos.y, -22f);
        this.lastRoomPos = roomPos;
    }

    private Vector3 lastRoomPos;

    private void DoExpend()
    {
        if (!this.isExpend)
        {
            this.isExpend = true;
            this.lastRoomPos = this.miniMapCam.transform.position;
            this.minimapImage.raycastTarget = false;
            this.minimapCanvas.DOFade(0, 0.1f)
            .OnComplete(() =>
            {
                this.minimapRect.localPosition = Vector3.zero;
                this.minimapRect.localScale = Vector3.one * 3.3f;
                this.miniMapCam.orthographicSize = 188f;
                this.minimapCanvas.DOFade(1, 0.1f)
                .OnComplete(() =>
                {
                    this.minimapImage.raycastTarget = true;
                });
            });
        }
        else
        {
            this.isExpend = false;
            this.minimapImage.raycastTarget = false;
            this.minimapCanvas.DOFade(0, 0.1f)
            .OnComplete(() =>
            {
                this.minimapRect.position = minimapPos;
                this.minimapRect.localScale = Vector3.one;
                this.miniMapCam.orthographicSize = 75f;
                this.minimapCanvas.DOFade(1, 0.1f)
                .OnComplete(() =>
                {
                    this.minimapImage.raycastTarget = true;
                    var pos = GameObject.FindGameObjectWithTag("Player").transform.position;
                    this.MiniMapUpdate(lastRoomPos);
                });
            });
        }
    }

    private IEnumerator mapFlickerling()
    {
        while (true)
        {
            this.txtMapCount.text = string.Format("Map Count : {0}", this.generator.wholeRoomList.Count);
            this.txtRowCol.text = string.Format("MaxRow  : {0}\nMaxCol  : {1} ", this.generator.maxRow, this.generator.maxCol);
            this.imgCurrentMap.SetActive(!this.imgCurrentMap.activeSelf);
            yield return new WaitForSeconds(0.5f);
        }
    }

    private void OnDisable()
    {
        this.minimapCanvas.DOKill();
    }
}
  • 코인 및 에테르 프리팹의 이미지 변경 및 상시 스핀하는 모습으로 구현, 및 획득시 이펙트 확인 가능

코드

 public void Init()
    {
        this.GetComponent<BoxCollider2D>().enabled = false;
        this.coinStartPos = this.transform.position;
        this.coinEndPos = this.transform.position + Vector3.up * this.coinMaxHeight;
        this.FieldCoinAimStart();
    }

    public void FieldCoinAimStart()
    {
        this.transform.DOLocalRotate(new Vector3(0, 720f, 0f), this.coinDuration * 2, RotateMode.LocalAxisAdd)
            .SetEase(Ease.Linear);
        this.transform.DOMove(this.coinEndPos, this.coinDuration)
            .SetEase(Ease.OutQuad)
            .OnComplete(() =>
            {
                DOTween.Sequence()
                    .AppendInterval(0.1f)
                    .OnComplete(() =>
                    {
                        this.transform.DOMove(this.coinStartPos, this.coinDuration)
                        .SetEase(Ease.InQuad)
                        .OnComplete(() =>
                        {
                            this.transform.DOLocalRotate
                            (new Vector3(0, 360f, 0f), this.coinDuration * 2, RotateMode.LocalAxisAdd)
                            .SetEase(Ease.Linear)  
                            .SetLoops(-1);
                            this.GetComponent<BoxCollider2D>().enabled = true;
                        });
                    });
            });
    }
  • 인벤토리에 아이템 추가시 연출 추가
    • 기본적으로는 꿀렁거리는 연출
    • 하지만 한번에 많은 양의 아이템을 먹는다면 점점 커지며 꿀렁거리게 됨

코드

 private float scaleDuration = 0.15f;
    private float maxScale = 1.2f;
    private float midleScale = 0.7f;
    private float finalScale = 1f;  

    private void ButtonScaleAnim()
    {
        this.btnTrans.DOKill();
        //this.btnTrans.localScale = this.btnOrgScale;
        this.maxScale += 0.1f;
        this.btnTrans.DOScale(this.maxScale, this.scaleDuration)
            .SetEase(Ease.OutQuad)
            .OnComplete(() =>
            {
                    this.btnTrans.DOScale(this.midleScale, this.scaleDuration)
                    .SetEase(Ease.InQuad) 
                    .OnComplete(() =>
                    {
                        this.btnTrans.DOScale(this.finalScale, this.scaleDuration)
                        .SetEase(Ease.OutQuad)
                        .OnComplete(() =>
                        {
                            this.maxScale = 1.2f;
                        }); 
                    });
            });
    }

    private void OnDisable()
    {
        this.txtFullField.DOKill();
        this.txtFullPopup.DOKill();
        this.txthealthField.DOKill();
        this.txtHeathPopup.DOKill();
        this.btnTrans.DOKill(); 
    }

 

 

이제 추가적인 연출들은 대부분 최종 기획에서도 따로 얘기하지 않은 부분들만 남아있어 더이상의 추가적인 구현 사항을 없을 예정이다.

하지만 금일 안드로이드 빌드이후 내부 테스트를 거처 추가적인 밸런스를 잡을때 어느정도 변경사항등이 있을 것으로 예상된다. 

 

우선 밸런싱에서 중요하게 생각해야 하는 부분은 게임의 핵심적인 부분인 핵앤 슬래시 적인 느낌과 적들을 쓸어버리는슈팅 게임 특유의 느낌 그리고 적절한 난이도를 목표로 삼아야 할듯 하다.

반응형
LIST