레이블이 게임개발인 게시물을 표시합니다. 모든 게시물 표시
레이블이 게임개발인 게시물을 표시합니다. 모든 게시물 표시

2017년 12월 1일 금요일

인벤토리 기초 구조 코드

다시 게임 제작개시, 이제 간단한 미니게임은 충분한 것 같고..
조금 더 나의 본질이 뭔가, 뭐가 하고 싶은가를 고민하다가 새 게임을 시작.

이번 게임은 수집, 성장 요소가 있는 게임이기 때문에 인벤토리가 필요해서 하나 만들었다.



간만에 풀코드.
InventorySystem.cs


using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Kpaper;

namespace Kpaper
{
    public class InventorySystem : MonoBehaviour
    {
        #region Inventory
        
        // 인벤토리 시스템 기초 구조만 담긴 코드
        // _itemID 를 itemTable 에서 찾아서 정보를 표시하거나 하는 부분은 별도로 구현해야 한다.

        // 아이템의 아이디 갯수 itemID, count
        public Dictionary items = new Dictionary();

        // items 에 입력한 아이템 ID와 카운트를 더해준다. (add 다. assign 아님)
        public void setAddItem(int _itemID, int _count)
        {
            // 아이템이 목록에 없다면 넣어준다.(초기 갯수는 0개)
            if (items.ContainsKey(_itemID) == false)
            {
                items.Add(_itemID, 0);
            }

            // 아이템 수량 증가 적용
            items[_itemID] += _count;

            if (Debug.isDebugBuild)
                Debug.Log(string.Format("{0} {1}을 {2} 개", "아이템 삽입", _itemID, _count));
        }

        // items 에서 해당 아이템 키가 있는지 확인하고 있으면 카운트 만큼 빼준다. 카운트가 0인 경우에는 아이템 키를 제거해준다.
        public void setRemoveItem(int _itemID, int _count)
        {
            // 아이템이 목록에 없다면 아무것도 하지 않는다.
            if (items.ContainsKey(_itemID) == false)
            {
                if (Debug.isDebugBuild)
                    Debug.Log("아이템이 목록에 없습니다.");
                return;
            }

            // 아이템 수량 감소 적용
            items[_itemID] -= _count;

            // 아이템 수를 감소 시켰더니 0개 이하이면 아이템을 사전 목록에서 제거한다.
            if (items[_itemID] <= 0)
                items.Remove(_itemID);

            if (Debug.isDebugBuild)
                Debug.Log(string.Format("{0} {1}을 {2} 개", "아이템 제거", _itemID, _count));
        }

        
        // 보유한 아이템 목록
        public List keys = new List();

        // 아이템 목록 새로 고침
        public void setRefreshInventory()
        {
            if (Debug.isDebugBuild)
                Debug.Log(items.Count + " 개의 아이템이 있습니다.");

            // 딕셔너리의 키 묶음을 들고와서 Keys 리스트를 만든다.
            keys = new List(items.Keys);

            // Keys 리스트를 기준으로 아이템 ID와 수량을 출력한다.
            for (int i = 0; i < keys.Count; i++)
            {
                int _itemID = keys[i];
                int _itemCount = items[_itemID];

                if (Debug.isDebugBuild)
                    Debug.Log("아이템 키 : " + _itemID + " 아이템 수량 : " + _itemCount); // 이 부분을 리스트로 만들어 쓰던가 하면 관리하기 편하다.
            }

        }

        // 아이템 아이디를 입력하면 해당 아이템의 보유 수량을 리턴한다. 아이템을 찾을 수 없으면 0을 보낸다.
        public int getItemCountByItemIndex(int _itemID)
        {
            if (items.ContainsKey(_itemID))
            {
                return items[_itemID];
            }
            else
            {
                Debug.Log(string.Format("인벤토리 안에서 찾을 수 없는 아이템ID {0} 를 요청했습니다.",_itemID));
                return 0;
            }
        }

        #endregion

        #region MonoBehavior

        private void Start()
        {
            // 시연
            
            // 임의로 1이라는 itemID를 가진 아이템을 10개 넣고 5개씩 2번 빼서 0으로 만들어 본다.

            // 인벤토리 리프레시
            setRefreshInventory();

            // 아이템 1을 10개 넣고
            setAddItem(1, 10);

            // 인벤토리 리프레시
            setRefreshInventory();

            // 아이템 갯수 찾기 테스트
            Debug.Log(getItemCountByItemIndex(2));

            // 1을 5개 제거
            setRemoveItem(1, 5);

            // 인벤토리 리프레시
            setRefreshInventory();

            // 1을 5개 제거
            setRemoveItem(1, 5);
            
            // 인벤토리 리프레시
            setRefreshInventory();

        }

        #endregion
    }
}

열정에 대해서


게임 개발은 역시 열정이 중요하다.

삶의 무게에 자꾸 꺼져간다.
그랬다가 다른 이의 작품을 보면 꺼져가던 불이 다시 불타오른다.

나는 아직 내 게임을 만들지 못했다.

2017년 9월 18일 월요일

Unity Custom Menu 만들기

귀찮은 작업이라고 생각해서 잘 안하는 편이었는데...
오늘 처럼 뭔가 단순하게 반복해야 하는 작업에는 메뉴로 등록하고 빨리 적용하는게 나을 것 같았다.

작업 내용은 어떠한가 하니
1. 어떤 오브젝트에 필요한 새 컴포넌트를 붙이고,
2. 구 컴포넌트의 값을 새 컴포넌트로 옮기고,
3. 구 컴포넌트를 삭제한 뒤,
4. 주석용으로 사용하는 컴포넌트를 붙여서 작성시각을 기록한다.

일괄로 하기엔 확인하면서 진행해야 해서 메뉴를 이용하는 정도가 딱 좋았다.
(컨텍스트 메뉴가 나았을지도? (웃음))

참고한 Document
https://docs.unity3d.com/ScriptReference/EditorGUILayout.html

예제는 이거면 금방 알 수 있다. (Toggle 레퍼런스에서 옮김)
필요한 변수를 선언하고
editorLayout 으로 연결하고
거기서 조작에 따라 처리할 내용을 기입하면 된다.


using UnityEngine;
using UnityEditor;

public class EditorGUILayoutToggle : UnityEditor.EditorWindow
{
    bool showBtn = true;

    [MenuItem("Examples/Editor GUILayout Toggle Usage")]
    static void Init()
    {
        EditorGUILayoutToggle window = (EditorGUILayoutToggle)EditorWindow.GetWindow(typeof(EditorGUILayoutToggle), true, "My Empty Window");
        window.Show();
    }

    void OnGUI()
    {
        showBtn = EditorGUILayout.Toggle("Show Button", showBtn);
        if (showBtn)
            if (GUILayout.Button("Close"))
                this.Close();
    }
}

2017년 7월 26일 수요일

어떤 오브젝트의 Mirror 된 회전 값은? (쿼터니언 거울 반전)

쿼터니언으로 미러링 할 때 메모

오일러앵글이 아니라 쿼터니언의 회전은 이해하기 어려울 수 있다.
회전각을 반전시키는 것은 더더욱...

예를 들기 위해 obj의 로컬로테이션을 미러하고 싶다고 가정했다.

보통은 아래와 같이 생각하지만,
new Quaternion(obj.localRotation.x * -1.0f, obj.localRotation.y, obj.localRotation.z, obj.localRotation.w);

실제로는 아래와 같아야 하고,
new Quaternion(obj.localRotation.x * -1.0f, obj.localRotation.y, obj.localRotation.z, obj.localRotation.w * -1.0f);

위도 비슷하지만 비틀림이 있기 때문에 아래와 같이 사용하는 것이 옳다.
new Quaternion(obj.localRotation.x, obj.localRotation.y * -1.0f, obj.localRotation.z * -1.0f, obj.localRotation.w);

참고 URL : https://www.gamedev.net/forums/topic/599824-mirroring-a-quaternion-against-the-yz-plane/


추가 메모  :
카메라 방향이 그대로 일 때 어떤 오브젝트의 이동과 회전을 거울 반전시키려면
포지션 x 축도 바꿔준다. (localPosition.x * - 0.1f)

2017년 6월 20일 화요일

Unity 엔진 난독화 도구 Obfuscator


최근 개발 중인 프로그램의 출시 시즌이라 이래저래 배포 문제를 해결하고 있다.

유니티로 개발한 프로그램은 Managed\Assembly_cshap.dll 파일에 C#으로 짠 코드 대부분이 쉽게 보이게 되는 문제가 있다.
쉽게 코드를 보고 변조할 수 없도록 Encryption 을 걸면 좋겠지만, C# 특성상 적용이 어렵다.

최소한 난독화라도 걸고 출시해야 할 것 같아서 여러가지 솔루션을 찾아봤는데...
난독화 도구로는 아래 에셋이 좋은 것 같다. (JJ 감사합니다.)

옵션은 조금 만져줘야 하지만, 크게 손이 안가고 가장 편하고 확실한 느낌이다.
(물론 맞춰서 코드도 조금 고쳐야 하긴 했지만)



사용법은 구입 -> 설치 -> Editor\Beebyte\Obfuscator\ 안의 옵션 파일을 설정해주면 된다.

2017년 5월 8일 월요일

새 게임 Live2D 모델링 중간 과정

새로 만들고 있는 게임(?)의 모델링 중간 과정
여러가지 시행착오도 겪고 팀원들끼리 감정도 조금씩 닳고 있고
 여러가지를 소모하면서 그래도 열심히 오늘도 게임을 만들고 있다.
 누군가가 재밌어 해주면 정말 좋겠다.
 개발 도중의 스크린샷 (여주인공) Vertex 가 선택된 화면만 보니 왠지 조금 무섭다. ^^;;

하지만 애정(?)을 담아 만들고 있으니까
그래도 비쥬얼은 볼만한 작품이 나올 듯
원화가 친구가 엄청 분발해주고 있어서 나도 자극이 된다.


2017년 4월 4일 화요일

마스크 오브젝트 쉐이더 간단하게 만들기

역시 일단 먼저 해봐야 해.

Unity 엔진 내에서 Shader 를 하나 만들고 아래의 코드를 입력한다.
그리고 Material 도 새로 만들어 조금전에 만든 Shader를 선택
(아래 코드는 Kpaper/MaskObj )

마스킹 오브젝트를 이용해서 AR 컨텐츠를 만드는데 사용하면 된다.

참 쉽죠?


Shader "Kpaper/MaskObj" {
 SubShader{
  // regular geometry 이후에 마스크를 render 한다.

  Tags{ "Queue" = "Background" }

  // RGBA 채널을 그리지 않는다, Depth buffer 로만 사용

  ColorMask 0
  ZWrite On

  // 패스에서는 아무것도 하지 않는다.

  Pass{
 }
 }
}


2017년 2월 21일 화요일

Unity3D 용 Json Parser - JsonUtility(Unity3D 5.3 Later), JsonObject

Unity3D로 Json 파일을 좀 사용할 일이 있어서 알아보았다.

그 동안 기획일 하면서 데이터만 만들었지,
직접 뭔가를 해볼일은 없었는데 이참에 해보는 것으로...

-------------

Unity3d Json Parser를 검색해보면

- JsonFX (가장 편하다는 평인데, 사이트 접속 불가. DLL 은 구했지만 스킵.)
- LitJson (iOS 이슈 게시물이 상당히 많다.. 위험)
- MiniJson (EastFever 님의 추천!!)
- JsonObject (직접 테스트 해본 것. 문제 없음)

등이 나오는데

일단은 JsonObject 를 사용해봤다.
이유는 Unity3D Asset Store에 등록되어있는데다가 무료고,
다들 잘 사용하고 있는 것 같아서 선택했다.

다운로드 및 레퍼런스 위키는 아래 주소에서 확인 가능하다.
http://wiki.unity3d.com/index.php/JSONObject#Download

나는 간단하게 읽고 쓰기만 할 생각이라서 뭐 다른건 지원된다고 해도 그러려니 상태였다.!
당연히 유니티 5.5에서도 문제 없었기에 이걸로 써야지~ 하고 결정!!!


-------------


그.. 그런데... 두둥!
조금 더 알아보다 보니,

유니티 5.3 부터 JsonUtility 라는 내장 API 가 생긴 것이다. 두두둥..!!

(몰랐다니, 아니 대수롭지 않게 보고 흘려서 까먹은듯,
릴리즈 블로그 읽기를 소홀히 한 제 탓입니다. T_T)

그래서 바로 쓱쓱 테스트 !!!

일단 레퍼런스 문서를 보자.
https://docs.unity3d.com/ScriptReference/JsonUtility.html


# ToJson 사용 방법 (코드 예제)


using UnityEngine;

[System.Serializable]
public class MyJsonClass
{
    // 사용할 Json Key 를 정의
    public int level;
    public float timeElapsed;
    public string playerName;

}

public class JsonUtilityTest : MonoBehaviour {

    private void WriteJSon() {
        MyJsonClass myObject = new MyJsonClass();
        myObject.level = 5;
        myObject.timeElapsed = 14.75f;
        myObject.playerName = "Kpaper ToJson Test";

        string json = JsonUtility.ToJson(myObject);
        Debug.Log(json);
    }
}

# FromJson 사용 방법. (더 자세한 내용은 위의 레퍼런스 사이트보면 잘 나와 있다.)


JsonUtility.FromJson<MyJsonClass>(json);

------

딱 내가 원하는 것만 간단하게 쓸 수 있어서 좋았다.
손쉽게 시리얼라이즈!

아무래도 엔진에 종속되서 개발을 하다 보니,
외부 에셋을 쓰기 보다는 내장된게 좋을 것 같아서 방향 선회!를 하는 것으로 결론...

끝!

P.S : 교훈. 멀리서 찾지 말자 -_-;;;

-----------------------------------------------------

[내용 업데이트]

으헉!!
JsonUtility는 Json 타입 중 Property Type 에는 사용할 수 있는데, Dictionary Type 은 사용할 수 없다.

구글 선생님한테 물어봐도 고통, 포럼 유저들도 다 같이 고통 중이었다.
(언젠간 업데이트 되지 않을까 하고 헛된 희망을 가져봤다.)

하지만 계속 구글링 해본 결과, 다행히 구글 선생님은 일본 블로그 하나를 추천해주셨다.
http://kou-yeung.hatenablog.com/entry/2015/12/31/014611
(杏仁さん、ありがとうございます。 T_Td)

ISerializationCallbackReceiver 를 이용하는 방법이다.

이걸로 거의 해결! (왜 거의인지는 나중에 다시 포스팅 하겠다. ㅜㅜ)

P.S 2 : 그냥 평범하게 선구자분들에게 추천 받은 것으로 할 걸, 왜 그랬을까. ㅠ_ㅠ...

<끝>

2017년 1월 30일 월요일

Live2D iOS Build 했을 때 얼굴 텍스쳐가 깨져 보이는 문제 해결

이번 설 연휴는 인디게임 제작에 많이 사용했다.

주로 노가다 하는데 사용했는데,
이번 프로젝트는 애니메이션 처리를 어떻게 할까 고민하다가 Live2D 를 사용하기로 했다.

인디팀으로 3인조인 우리에게
일일히 유니티 기능을 다 가르치는 것보다,
Live2D 애니메이터 툴을 사용하는 편이
일반인이 보편적인 개념으로 키 애니메이션 잡기에 좋을 것 같다고 판단했기 때문

그리고 유니티 소스를 건드리다가 사고가 나는 경우도 적을 것이고...
모델링은 내가 할 수 밖에 없는게 문제지만

그래서 여주인공을 모델링 했다.
(한명 만드는데 시행착오가 많아서 10번쯤 다시 만든듯... ㅠㅠ 약 30시간 정도 소비)


이 과정에서 발생한 귀찮고 심각한 문제가 하나 있다.

안드로이드 빌드에서는 문제가 없었는데,
같은 세팅의 iOS 빌드 에서는 그래픽이 꺠져보이는 현상이 발생했다.



좀 찾아보니 텍스쳐 랜더 관련 문제인 것 같아서
해당하는 모델 데이터의 텍스쳐 세팅을 바꿔준다.




기껏 만든 모델이다 고해상도라 조금 부담은 되지만,
그래도 깔끔하게 보여지고 싶었기에 아래와 같이 변경.

Override for iOS
Texture Size 설정 (1:1)
RGBA 16Bit

이렇게 해서 확인해보면 해결!

------------

아마 유니티 5.5 이후 버전에서 뭔가 바뀌면서 발생한 문제인 듯.
옛날에는 경험한 적이 없다.

작업한 캐릭터도,
나중에 좀 정리가 되었을 때 블로그에서 소개할 수 있을 정도가 되면 좋겠다.. ^^;

2017년 1월 24일 화요일

게임 시나리오를 구성할 때 생각하면 좋은 템플릿

최근 시나리오 단편을 이것저것 적어보려고 노력하고는 있는데 잘 안된다 ^^;;
그렇지만 아무리 졸스러운 습작이라도 뭐라도 쓰면 변화하는 것을 느낄 수 있다.
중요한 것은 포기하지 않고 끝까지 써야하는 것이고,
그렇게 되면 그게 경험치가 되어 레벨업을 할 수 있다.

------------------

하나의 이야기를 구성할 때 아래의 템플릿을 활용하면 좋다.
간단히 한 두줄씩이라도 써놓고 이야기를 풀어나가기 시작하면 막혔을 때 도움이 된다.

게임 이외의 시나리오에도 적용할 수 있다.

템플릿의 기본은 5W1H + 알파

1. 이 이야기의 매력포인트 한줄 정의
2. 언제
3. 어디서
4. 누가
5. 무엇을
6. 왜
7. 대립하는 상대는?
8. 어떻게 시작해서?
9. 어떻게 끝나는 이야기?
10. 그래서 이 이야기의 제목은?

2017년 1월 1일 일요일

[MikuFly] 안드로이드 버전 릴리즈

캐쥬얼 액션 미니 게임 "MikuFly (미쿠플라이)" 릴리즈 했습니다. 

플래피버드 스타일의 팬게임입니다. 미쿠가 귀여우니 한번 플레이 해보세요.
캐릭터 저작권은 PCL(PIAPRO CHARACTER LICENSE)를 따르고 있습니다.(http://piapro.jp/license/pcl/summary)



[간단한 설명]
 - 100% 취미 게임입니다. (대부분의 코드, 그래픽 리소스 자체 제작)
 - 그리고 조금 열받는 게임입니다만, 요령을 잡으면 반드시 멀리 날 수 있게 했습니다.

 - 무료 게임이고, 플레이 횟수 제한도 없고, 게임 플레이에 광고는 표시하지 않습니다.
 - Google Play Game Service  에 로그인 하면 랭킹도 사용할 수 있게 됩니다.
 - 파일 읽기 쓰기 권한은 스크린샷을 찍어 트위터에 올리는 기능을 위해 사용합니다.
 - 구글 TV 를 지원합니다. (넥서스 플레이어에서 확인, 리모트나 게임패드로도 플레이 가능)
 - TV모드는 가로, 핸드모드는 세로로 플레이할 수 있습니다.

[다운로드]
구글 플레이 다운로드 링크 : http://goo.gl/1pW1aI

------------------------------

만들긴 꽤 오래전에 만들었는데...
광고는 할 정도가 못 된다고 생각해서 굳이 올리지 않았습니다만...

제법 여기저기서 받아주신 전세계의 여러분 감사합니다.