블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2859)
Unity3D (898)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (192)
협업 (64)
3DS Max (3)
Game (12)
Utility (142)
Etc (99)
Link (34)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (19)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

우선, 유니티에서 Window -> Services 합니다.



그러고 나면 Inspector 옆에 Services라는 텝이 생기는데 

Select Organization 하고 Create 해줍니다.



그러면 유니티에서 제공하는 Service들이 보일 것입니다.

그 중에, OFF상태인 In-App Purchasing 텝을 클릭합니다.



우측상단에 있는 토글을 눌러 OFF되어있던 상태를 ON으로 만들어줍니다.

그리고 13세 이하 어린이에게 지도감독이 필요한 지 여부를 선택하고 Save Changes 합니다.



이제, 프로젝트에 In-App Purchasing이 활성화 된 모습을 보실 수 있을 것입니다.

여기서 잊지말고 Import 버튼을 꼬옥 눌러줍니다!



프로젝트 뷰에 Unity IAP 플러그인이 제대로 임포트 된 모습입니다.



이제 기본 세팅이 다 되었습니다. 그렇다면 코딩을 해볼까요?

아래와 같이 Script를 작성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
using System;
using UnityEngine;
using UnityEngine.Purchasing;
 
public class InAppPurchaser : MonoBehaviour, IStoreListener
{
    private static IStoreController storeController;
    private static IExtensionProvider extensionProvider;
 
    #region 상품ID
    // 상품ID는 구글 개발자 콘솔에 등록한 상품ID와 동일하게 해주세요.
    public const string productId1 = "gem1";
    public const string productId2 = "gem2";
    public const string productId3 = "gem3";
    public const string productId4 = "gem4";
    public const string productId5 = "gem5";
    #endregion
 
    void Start()
    {
        InitializePurchasing();
    }
 
    private bool IsInitialized()
    {
        return (storeController != null && extensionProvider != null);
    }
 
    public void InitializePurchasing()
    {
        if (IsInitialized())
            return;
 
        var module = StandardPurchasingModule.Instance();
 
        ConfigurationBuilder builder = ConfigurationBuilder.Instance(module);
 
        builder.AddProduct(productId1, ProductType.Consumable, new IDs
        {
            { productId1, AppleAppStore.Name },
            { productId1, GooglePlay.Name },
        });
 
        builder.AddProduct(productId2, ProductType.Consumable, new IDs
        {
            { productId2, AppleAppStore.Name },
            { productId2, GooglePlay.Name }, }
        );
 
        builder.AddProduct(productId3, ProductType.Consumable, new IDs
        {
            { productId3, AppleAppStore.Name },
            { productId3, GooglePlay.Name },
        });
 
        builder.AddProduct(productId4, ProductType.Consumable, new IDs
        {
            { productId4, AppleAppStore.Name },
            { productId4, GooglePlay.Name },
        });
 
        builder.AddProduct(productId5, ProductType.Consumable, new IDs
        {
            { productId5, AppleAppStore.Name },
            { productId5, GooglePlay.Name },
        });
 
        UnityPurchasing.Initialize(this, builder);
    }
 
    public void BuyProductID(string productId)
    {
        try
        {
            if (IsInitialized())
            {
                Product p = storeController.products.WithID(productId);
 
                if (p != null && p.availableToPurchase)
                {
                    Debug.Log(string.Format("Purchasing product asychronously: '{0}'", p.definition.id));
                    storeController.InitiatePurchase(p);
                }
                else
                {
                    Debug.Log("BuyProductID: FAIL. Not purchasing product, either is not found or is not available for purchase");
                }
            }
            else
            {
                Debug.Log("BuyProductID FAIL. Not initialized.");
            }
        }
        catch (Exception e)
        {
            Debug.Log("BuyProductID: FAIL. Exception during purchase. " + e);
        }
    }
 
    public void RestorePurchase()
    {
        if (!IsInitialized())
        {
            Debug.Log("RestorePurchases FAIL. Not initialized.");
            return;
        }
 
        if (Application.platform == RuntimePlatform.IPhonePlayer || Application.platform == RuntimePlatform.OSXPlayer)
        {
            Debug.Log("RestorePurchases started ...");
 
            var apple = extensionProvider.GetExtension<IAppleExtensions>();
 
            apple.RestoreTransactions
                (
                    (result) => { Debug.Log("RestorePurchases continuing: " + result + ". If no further messages, no purchases available to restore."); }
                );
        }
        else
        {
            Debug.Log("RestorePurchases FAIL. Not supported on this platform. Current = " + Application.platform);
        }
    }
 
    public void OnInitialized(IStoreController sc, IExtensionProvider ep)
    {
        Debug.Log("OnInitialized : PASS");
 
        storeController = sc;
        extensionProvider = ep;
    }
 
    public void OnInitializeFailed(InitializationFailureReason reason)
    {
        Debug.Log("OnInitializeFailed InitializationFailureReason:" + reason);
    }
 
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
    {
        Debug.Log(string.Format("ProcessPurchase: PASS. Product: '{0}'", args.purchasedProduct.definition.id));
 
        switch (args.purchasedProduct.definition.id)
        {
            case productId1:
 
                // ex) gem 10개 지급
 
                break;
 
            case productId2:
 
                // ex) gem 50개 지급
 
                break;
 
            case productId3:
 
                // ex) gem 100개 지급
 
                break;
 
            case productId4:
 
                // ex) gem 300개 지급
 
                break;
 
            case productId5:
 
                // ex) gem 500개 지급
 
                break;
        }
 
        return PurchaseProcessingResult.Complete;
    }
 
    public void OnPurchaseFailed(Product product, PurchaseFailureReason failureReason)
    {
        Debug.Log(string.Format("OnPurchaseFailed: FAIL. Product: '{0}', PurchaseFailureReason: {1}", product.definition.storeSpecificId, failureReason));
    }
}
 
cs



결제를 진행해야하는 부분에서 


위의 BuyProductID 함수의 파라미터로 상품ID를 넣고 콜(구매요청)하면


product가 initialize된 후 ProcessPurchase로 결과가 넘어오는데


args.purchasedProduct.definition.id로 구매요청된 상품ID를 판별하여


상품에 맞는 보상을 지급해주면 됩니다. 참 쉽죠?


유니티 5.3버전 이전에는(유니티가 자체 IAP를 지원하기 전) Android와 iOS 각각 따로 결제시스템을 만들어야했는데


지금은 Android와 iOS를 동시에 지원해주기 때문에 정말 편하답니다~


    


결제된 정보는 구글 Payments 판매자 센터에서 확인하실 수 있습니다. (https://wallet.google.com/merchant)



출처: http://minhyeokism.tistory.com/47 [programmer-dominic.kim]



반응형
Posted by blueasa
, |

유니티 엔진 사용 시 입력을 하지 않으면 모바일 장치의 화면이 어두워지다가 잠기게 되는데, 그러면 플레이어는 잠김을 다시 풀어야 해서 불편합니다. 따라서 화면 잠금 방지 기능 추가는 필수적이고, Screen.sleepTimeout를 아래처럼 설정하면 그걸 할 수 있습니다.

1
Screen.sleepTimeout = SleepTimeout.NeverSleep;

참고:


[출처] https://sunhyeon.wordpress.com/2014/03/26/1400/

반응형
Posted by blueasa
, |

저도 동일한 문제로 헤매다가 
http://answers.unity3d.com/questions/1320150/unable-to-list-target-platform.html 
참고하여 해결했습니다. 
위 링크 들어가 보시면 댓글에 해결책이 있는데 
여기에 요약하면 
Android SDK tools 가 최신 버전(25.3.1)으로 업데이트 되면서 unity가 사용하던 기능이 없어진거 같다고 합니다. 
해결책은 기존 Android SDK설치 폴더에서 tools 폴더 이름을 변경한 후 [Your Android SDK root]/tools -> toolsXXXX  
http://dl-ssl.google.com/android/repository/tools_r25.2.5-windows.zip 를 다운로드 받아서 압축 풀고 해당 tools 폴더를 위의 
Android SDK설치 폴더에 복사합니다. 그러면 unity에서 예전처럼 잘 됩니다.



[출처] http://devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=79671&&#c_81343


[참조] http://answers.unity3d.com/questions/1320150/unable-to-list-target-platform.html


[참조] https://arincblossom.wordpress.com/2017/03/25/%EC%9C%A0%EB%8B%88%ED%8B%B0-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0-unable-to-list-target-platforms-please-make-sure-the-android-sdk-path-is-correct/comment-page-1/

반응형
Posted by blueasa
, |

NGUI 를 사용하면서 일반 오브젝트와 UI 오브젝트의 입력(터치)을 어떻게 처리해야 할지 알아본다.



일단, 보통은 게임에서 사용하는 Main Camera와 NGUI > Create UI 를 통해 생성되는 2D Camera(UI Camera) 두개(혹은 그 이상)를 사용할 것이다.


당연히 UICamera에 추가되는 Widget들은 UICamera 의 통제에 의해 OnHover, OnClick 등의 이벤트를 받는다.


하지만 게임오브젝트를 선택하려면? 당신은 여러가지의 고민을 하게된다.

'UI의 이벤트를 받지 않으려면?', '혹은 UI를 클릭했을때 게임오브젝트의 클릭을 무시하려면?' 등등...

하여, 이를 해결하기 위해 Picking Manager 라던지 NGUI의 메시지를 무시하는 플래그를 작성하던지의 시도를 해볼것이다.


NGUI는 이 상황에 대해 다음을 권고한다.


'모든 카메라에 UICamera 컴포넌트를 추가하세요!' 


일단 NGUI:UICamera 의 내용을 보면, UI카메라에 추가되었을경우엔 UI 들에게, Main Camera에 추가하면 인게임 오브젝트들에게 특정 이벤트 메시지를 보낸다고 써져있다. 본문


이벤트는 다음 링크를 참고한다. 이벤트



실제로 테스트 해본 결과,


1. 같은 레이어상의 UI와 non-UI 오브젝트(in-game object)로 테스트 시.

2개의 카메라(Main-Camera, UI-Camera)에 각각 UICamera 컴포넌트를 포함시킨후 실험.

NGUI Widget 툴을 통해 UI-Camera에 바탕 윈도우와 버튼을 하나 추가했다.

테스트를 위해 2개의 큐브를 씬에 추가. 스크립트를 작성하되, void OnClick() 함수를 추가했다.



테스트 결과, 버튼 영역을 클릭했을때, UIButton만 동작되었다.

게임 오브젝트 클릭시 OnClick이벤트가 정상 동작되었으며, 깊이에 따라 먼저 클릭된 게임오브젝트만 동작되었다.

버튼 영역을 제외한 UI윈도우 영역은 클릭테스트에 제외되며, 게임 오브젝트가 하단에 존재하면 게임오브젝트 이벤트가 호출된다.


- UI윈도우도 클릭테스트에 포함시키기 위해서는 Add Component > Physics > Box Collider 를 추가해준다. 추가후에는 윈도우에서 이벤트를 처리하기 때문에 윈도우 영역 클릭시 게임 오브젝트는 이벤트를 받지 않는다.


- 버튼이 isEnable=false; 되어있다면, 이벤트를 받지 않는다.


2. UI 부분을 다른 레이어로 세팅.

- 동일한 레이어일때와 결과가 같다.



즉, 이왕 NGUI를 사용한다면, 모든 카메라에 UICamera 컴포넌트를 추가하고, 입력이 필요한 오브젝트 마다 이벤트 함수를 추가해주자.



출처: http://toymaker.tistory.com/entry/NGUI-UI와-일반-오브젝트의-터치-이벤트-처리 [ToyMaker]

반응형
Posted by blueasa
, |


[링크] http://m.blog.daum.net/zevie/21

반응형
Posted by blueasa
, |



[링크] http://ijemin.com/blog/5385

반응형
Posted by blueasa
, |

UnityWebRequest를 이용해서 원격 서버에서 받아온 에셋 번들을 로컬 저장소에 저장하는 방법

유니티 5.6 문서에서는 알려주지 않는 로컬 저장소 저장 방법

유니티 5.6 문서에서는 웹 서버에서 에셋 번들을 받아올 때 WWW.LoadFromCacheOrDownload 대신에 UnityWebRequest와 DownloadHandlerAssetBundle을 사용할 것을 권장하고 있다. 아래의 코드가 유니티 5.6 문서에서 보여주는 웹 서버에서 에셋 번들을 받아와서 메모리에 로드하는 예제이다.

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}


출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}


출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}


출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}


출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]
using UnityEngine;
using UnityEngine.Networking;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;

public class UnityWebRequestExample : MonoBehaviour
{
IEnumerator InstantiateObject()
{
string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;
UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.GetAssetBundle(uri, 0);
yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);

GameObject cube = bundle.LoadAsset<GameObject>("Cube");
GameObject sprite = bundle.LoadAsset<GameObject>("Sprite");

Instantiate(cube);
Instantiate(sprite);
}
}


출처: http://wergia.tistory.com/32 [베르의 프로그래밍 노트]

서버에서 받아온 에셋 번들을 메모리에 넣어두고 사용하고자 하는 목적이 아니라 받아온 에셋 번들을 클라이언트의 로컬 저장소에 저장하고 패치하는 시스템을 만들고자할 때에는 부적절한 예제이며, 로컬 저장소에 저장하는 방법은 유니티 5.6의 문서에서는 알려주지 않는다.



에셋 번들을 로컬 저장소에 저장하는 방법

서버에서 받아온 에셋 번들을 로컬 저장소에 저장하려면 받아온 데이터를 파일 입출력을 해야했는데, 그러기 위해서는 우선 받아온 에셋 번들의 데이터, byte[] data를 찾아내고 거기에 엑세스할 수 있어야 했다. 그래서 첫 번째로 시도한 방법이 위의 예제에서 UnitWebRequest.GetAssetBundle()로 받아온  UnityWebRequest request에서 request.downloadHandler.data를 통해서 접근하는 것이었다.

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{
public string[] assetBundleNames;

IEnumerator AccessFailMethod()
{

string uri = "http://127.0.0.1/character";


UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri);

yield return request.Send();
string assetBundleDirectory = "Assets/AssetBundles";

if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}

FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();
}
}

하지만 위의 방법은 에셋 번들에 대한 원시 데이터 접근은 지원하지 않는다는 예외를 발생시키고 실패한다. 즉, GetAssetBundle로 웹 서버에서 불러온 데이터는 데이터에 대한 직접 접근을 허용하지 않으니 파일 입출력을 통해서 로컬 저장소에 저장할 수 없다는 것이다.


그렇기 때문에 로컬 저장소에 저장하기 위해서는 웹 서버에서 에셋 번들을 받아올 때 다른 방법을 취해야 했다. 아래의 예제가 다른 방식으로 웹 서버에서 에셋 번들을 받아와서 로컬 저장소에 저장하는 예제이다 :

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{

// 서버에서 받아오고자 하는 에셋 번들의 이름 목록

// 지금은 간단한 배열 형태를 사용하고 있지만 이후에는

// xml이나 json을 사용하여 현재 가지고 있는 에셋 번들의 버전을 함께 넣어주고

// 서버의 에셋 번들 버전 정보를 비교해서 받아오는 것이 좋다.
public string[] assetBundleNames;

IEnumerator SaveAssetBundleOnDisk()
{

// 에셋 번들을 받아오고자하는 서버의 주소

// 지금은 주소와 에셋 번들 이름을 함께 묶어 두었지만

// 주소 + 에셋 번들 이름 형태를 띄는 것이 좋다.
string uri = "http://127.0.0.1/character";


// 웹 서버에 요청을 생성한다.
UnityWebRequest request = UnityWebRequest.Get(uri);
yield return request.Send();


// 에셋 번들을 저장할 경로

string assetBundleDirectory = "Assets/AssetBundles";
// 에셋 번들을 저장할 경로의 폴더가 존재하지 않는다면 생성시킨다.
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}


// 파일 입출력을 통해 받아온 에셋을 저장하는 과정
FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();
}
}

위 예제에서 보다시피 UnityWebRequest.Get() API를 사용했을 경우 받아온 에셋 번들의 원시 데이터에 대한 접근이 가능해진다. 이로 인해서 파일 입출력을 통한 원격 서버에서 받아온 에셋 번들의 로컬 저장소 저장에 성공하게 되었다.



파일 입출력을 통한 저장 방법

받아온 에셋 번들을 파일 입출력을 통해 로컬 저장소에 저장하는 방법은 여러가지가 있다. 적당하다고 생각되는 방법을 골라서 사용하면 될 것이다.

// 파일 저장 방법 1
FileStream fs = new FileStream(assetBundleDirectory + "/" + "character.unity3d", System.IO.FileMode.Create);
fs.Write(request.downloadHandler.data, 0, (int)request.downloadedBytes);
fs.Close();

// 파일 저장 방법 2
File.WriteAllBytes(assetBundleDirectory + "/" + "character.unity3d", request.downloadHandler.data);
 

// 파일 저장 방법 3
for (ulong i = 0; i < request.downloadedBytes; i++)
{
fs.WriteByte(request.downloadHandler.data[i]);
// 저장 진척도 표시

}



로컬 저장소에 저장한 에셋 번들을 불러와서 사용하는 방법

위의 과정을 통해 원격 서버에서 받아온 에셋 번들을 로컬 저장소에 저장하는데 성공했다. 이 다음에 해야할 작업은 저장한 에셋 번들을 불러와서 사용하는 것이다. 그 작업은 유니티 5.6 문서에 나오는 기본 예제를 구현하는 것으로 충분히 가능하다.

using System.IO;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class AssetLoader : MonoBehaviour
{
IEnumerator LoadAssetFromLocalDisk()
{
string assetBundleDirectory = "Assets/AssetBundles";
// 저장한 에셋 번들로부터 에셋 불러오기
var myLoadedAssetBundle = AssetBundle.LoadFromFile(Path.Combine(assetBundleDirectory + "/", "character.unity3d"));
if (myLoadedAssetBundle == null)
{
Debug.Log("Failed to load AssetBundle!");
yield break;
}
else
Debug.Log("Successed to load AssetBundle!");

var prefab = myLoadedAssetBundle.LoadAsset<GameObject>("P_C0001");
Instantiate(prefab, Vector3.zero, Quaternion.identity);
}
}



출처: http://wergia.tistory.com/36 [베르의 프로그래밍 노트]

반응형
Posted by blueasa
, |

5.2 이후 바뀐 에셋번들을 처음 접해봤는데 이전보다는 심플해져서 사용하긴 쉬운 것 같다.


근데 서버에서 외부(앱 내 저장 가능한 공간 : Application.persistentDataPath 사용)에 다운로드를 받고 로드 할 때 삽질한 내용을 간단하게 올려 놓는다.


지금은 바빠서..


간단하게 올리고 나중에 퇴고를 해야겠다..



[삽질_1]

- PC에서는 잘되는데 Android에서 Application.persistentDataPath로만 접근 하는데,

  Write 할 때 Path가 mnt로 시작하는 외부 저장소 Path로 저장 됨.

  AssetBundle을 로드 하기 위해 Read 하려고 접근하니 Stroage로 시작하는 내부 저장소 Path를 줌.

[처리_1]

- 우선 강제로 내부 저장소만 사용하도록 프로젝트 셋팅에서 변경

   (Project Settings-Android-Configuration-Write Permission 을 Internal로 변경)



[삽질_2]

- 빈번하게 에셋번들 로컬 로드 시, 무한루프에 빠짐

[처리_2]

- 처리하기 편하려고 BundleName과 AssetName을 같게 했는데 유니티가 헷갈려하면서 뭔가 문제가 생기는 것 같아서

  BundleName 셋팅에 확장자를 추가(인스펙터에서 셋팅)하니 잘 됨.



[삽질_3]

- 제대로 다하고 올린 것 같은데 이전에 잘 로드 되던 파일이 에러가 나서 당황함.


[처리_3]

- 파일질라로 에셋번들 파일을 업로드 할 때 Binary로 올리지 않으면 문제가 생긴다고 함.

  파일질라 셋팅을 수정하고 다시 업로드 해서 해결

  (전송-전송 유형-바이너리 로 변경)

- [참조] http://blueasa.tistory.com/2110

  


반응형
Posted by blueasa
, |

http://www.forest.impress.co.jp/docs/news/20140627_655577.html

 

먼저 E-Motion 에 관한 내용 입니다.

 

http://emote2.mtwo.co.jp/index.php

요기는 홈페이지

 

다른것 보다 눈에 띄는건, 유니티에 넣을수 있다는 점 이네요. Live2D의 경우에 인티그레이션이 되어있었나;;가물가물 합니다.

안드로이드, ISO, PSP, 3DS, PSVITA라거나  플스3, 엑박 다 호환되는듯 합니다.

 

피쳐를 살펴보면, E-motion은 유니티에 대응해, 보다 범용적으로 사용할 수 있게 되었다고 합니다.   물론 유니티 Pro대응입니다.

 

E-mote의 캐릭터 생성

기본 제작은 PSD로 조각조각 그린 그림을 가져와서, 이미지를 구부리거나 휘거나 돌리는 등? 으로 작업을 합니다.   일단 인티그레이션이 Live2D에 비해 잘 되어있는것 같고, 유니티에서 바로 쓸수 있는거 같아서??(확인은 해봐야 합니다)  맘에 드네요.

 

PSD 원화 만들기E-mote에 PSD를 캡처

타임 라인에서 애니메이션 - 숀을 낸다

 

대략 위와 같은 느낌??

 

 

 

다운로드는 아래 링크를 따라가세요~

 

http://emote2.mtwo.co.jp/download.php

 

물론, 그때그때 업데이트가 됩니다.

 

자주 업데이트가 되니, 잘 읽어보시고 다운로드 받으시기 바랍니다.  평가판을 받아서 써 볼 수 있습니다.  평가판은 90일간 사용해 볼 수 있습니다.   가격도 Live2D보다 저렴한거 같네요.



[출처] E-Motion . . . Live 2D 와 비슷한 계열의 툴. |작성자 세라프


반응형
Posted by blueasa
, |

Answer by Diet-Chugg 

If you are using FIlezilla to upload your asset bundles. Try inside of FIlezilla Transfer>Transfer Type>BInary. then delete your build and asset bundles and re-upload them. It worked for me.

[한글] 전송-전송 유형-바이너리 로 변경



[출처] http://answers.unity3d.com/questions/1140569/error-failed-to-decompress-data-for-the-assetbundl.html

반응형
Posted by blueasa
, |