336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

[Unity3D] 안드로이드 플러그인 만들기(안드로이드 스튜디오 2.3.3)


build.gradle

 


기존 포스팅에서 안드로이드 스튜이도 2.1.1로 플러그인을 만들었는데,

 

안드로이드 스튜디오가 업데이트 되면서 release 폴더가 안생기는 문제가 있었습니다.

 

그래서 많은 분들이 댓글을 달아주셨는데, 이제서야 포스팅을 하네요.

 

간략하게 쓰도록 하겠습니다. (순서 이미지는 다 있습니다.)

 

잘 안되시는 분들은 기존 포스팅 참고 하시면 수월하십니다.

 

 

안드로이드 스튜디오(Android Studio)를 실행하여 New Proejct를 하고,

 

Application name과 Company domain을 써줍니다.

 

실제 사용은 하지 않을 클래스 입니다. 아무거나 치셔도 됩니다. 그리고 Next를 눌러줍니다.

 

 

 

Phone과 Tablet에서 사용할 예정이니 그대로 Next를 눌러줍니다.

 

 

 

그리고 Empty Activity를 선택하고 Next를 눌러줍니다.

 

 

아래 체크 박스들은 쓸 일이 없으므로, 체크 해제 해주시고,

 

Activity Name도 그냥 두시기 바랍니다. (사용하지 않습니다)

 

그리고 Next를 눌러줍니다.

 

 

완료되었으면, 이제 File->New Module을 눌러줍니다.

 

 

 

기존에는 프로젝트 생성해서 바로 했지만, 이제 모듈을 추가해서 할 예정입니다.

 

Android Library를 선택하고 Next를 눌러줍니다.

 

 

 

라이브러리 이름을 작성하시고 Finish를 눌러줍니다.

 

 

 

방금 만든 모듈 루트에서 마우스 오른쪽을 눌러

 

Open Module Settings를 눌러줍니다.

 

UnityActivity를 사용하기 위해, Unity에 있는 classes.jar를 추가할 것입니다.

 

 

 

방금 만든 모듈이 선택되어있는지 재 확인 하시고,

 

Dependenceis로 가서 + 버튼을 누른 후 Jar dependency를 눌러줍니다.

 

 

 

현재 저는 Unity 5.3를 사용중입니다.(classes.jar 파일의 경로가 예전 버전과 달라졌습니다.)

 

만약 해당 파일이 존재하지 않는다면(예전 버전이라면)

 

이전 포스팅을 참고해주세요.

 

classes.jar 파일을 복사해서, 다음 경로(바로 윗 단계에서 경로 확인가능)에 붙여넣기 해줍니다.

 

 

 

넣어주고 다음 화면으로 돌아오면,  아래 이미지처럼 jar파일이 들어간 것을 확인할 수 있습니다.

 

 

 

확인을 눌러주시고, 좀전에 만든 모듈의 다음 패키지에서

 

마우스 오른쪽을 눌러 새로운 Java Class를 만들어 줍니다.

 

 

 

이름은 MyPluginActivity로 하겠습니다. 그리고 확인을 눌러줍니다.

 

 

 

거의 완료가 되었습니다.

 

테스트 할 수 있도록 몇개의 함수를 만들어 줍니다.

 

 

 

 

그리고 좌측에 Gradle을 통해 jar파일을 만들 예정입니다.

 

myplugin 모듈 이름이 써있는 build.gradle을 더블클릭해서

 

스크립트를 열어줍니다.

 

다음은 몇가지를 추가하여 작성한 파일입니다.

 

 

 

위 스크립트 내용입니다.

apply plugin: 'com.android.library'

android {
compileSdkVersion 26
buildToolsVersion "26.0.0"
publishNonDefault true
defaultConfig {
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.+'
testCompile 'junit:junit:4.12'
compile files('libs/classes.jar')
}

task deleteObjectJar(type: Delete){
delete 'release/AndroidPlugin.jar'
}

task exportJar(type: Copy){
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteObjectJar, build)

 

 

다 작성하였으면 Build->Clean Project를 한번 해줍니다.

 

 

 

그리고 안드로이드 스튜디오 우측에 있는 Gradle을 눌러

 

myplugin->Tasks->other->exportJar를 더블클릭해줍니다.

 

 

 

그러면 다음처럼 프로젝트 폴더 release쪽에 jar파일이 나온것을 확인할 수 있습니다.

 

 

도움되셨길 바랍니다.

 

질문은 댓글 달아주세요^^

 


******************* 추가 *****************

Plugin 모듈을 추가 하셨는데, 그 모듈의 gradle 파일을 첨부하였습니다.


모듈 gradle을 설정하고, 이를 실행시켜야 release 폴더가 나옵니다.


프로젝트 만들 때 지정한 그 프로젝트가 아니라, 


추가한 모듈입니다. 이점 헷갈리시지 마세요.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


유니티3D 안드로이드(Android) 플러그인(Plugin) 만들기(추가)


[UNITY] 안드로이드 플러그인 만들기 에 추가적으로 하나더 써보려고 합니다.


Java 코드단에서 UnityPlayerActivity를 상속 받는 곳에서 구현을 했었는데,


그게 아닌 타 클래스 만들어서 하는 부분도 추가합니다. 


Java에서 타 클래스를 만들고 구현을 한 다음 Unity에서 클래스를 찾아서 호출하면 됩니다.


간단히 예를 들겠습니다.



< Java >


1. 프로젝트 만들고(패키지명은 원하시는걸로), 클래스를 하나 추가합니다.


여기에서는 TestAClass가 새로 생성한 클래스 입니다.




2. 기본 클래스 파일입니다. UnityPlayerActivity를 상속해 줍니다.


* UnityPlayerActivity상속없이 자바 클래스만 추가해서 되는지는 아직 못해봤네요. 혹 해보신분 댓글로 부탁드립니다.




3. 유니티애서 호출할 클래스 입니다. 


간단히 GetSum()이라는 함수만 추가하겠습니다.





< Unity >

* 우선 AndroidManifest.xml 확인해주세요. 많은 분들이 패키지명이 달라서 안된경우가 많았습니다.


using UnityEngine;
using System.Collections;

public class PluginCalling : MonoBehaviour {

    private static AndroidJavaObject myObj;

    string messge = "init";

	// Use this for initialization
	void Start () {
#if UNITY_ANDROID && !UNITY_EDITOR
	    myObj = new AndroidJavaObject( "com.mine.androidplugin.TestAClass" );
#endif
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    void OnGUI()
    {
        // 이렇게 접근하는 방법은, static이나 non-static 모두
        // 동일한 방법으로 접근 가능하다
        if (GUI.Button(new Rect(100, 100, 100, 50), "GetSum"))
        {
#if UNITY_ANDROID && !UNITY_EDITOR
            messge += ("\n" + myObj.Call("GetSum", 123, 456).ToString());
#endif
        }

        GUI.Label(new Rect(Screen.width / 2 - 350, Screen.height / 2 - 150, 700, 300), messge);
    }
}


별거 없네요. 그냥 AndroidJavaObject로 오브젝트 생성하고 호출하는 것 입니다.


도움되셨길 바랍니다.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


- NGUI 버전 : 3.9.8 -


NGUI 토글버튼 기초


게임을 구현하다 보면, 토글 버튼이라던가 라디오버튼이 필요할 때가 있습니다.


이를 위해 NGUI에서는 UIToggle이라는 컴포넌트를 제공합니다.


이 기능에 대해 간단하게 알아보고, 다음 포스팅에서 


제어할 수 있게 구현하도록 하겠습니다.



* 포스팅에 사용되는 이미지는 유료라서 공유가 힘듭니다. 양해바랍니다.


우선 아래 그림처럼 배치를 하도록 합니다.  


ToggleA(Gray)는 빈 게임오브젝트 이며, 자식으로 버튼들이 들어갑니다.


NGUI에서 기본 뼈대 만드는 법과, Button 만드는 법은 다음을 참고하세요.


[NGUI] 스프라이트(SPRITE)


[NGUI] 버튼과 레이블




이제 ToggleA(Gray)게임 오브젝트에 


UIToggle과 UIToggleComponents를 추가합니다.


(나머지도 동일하게 추가합니다)


Box Collider넣고 Size 설정하는거 잊지 마시기 바랍니다.


그리고 아래 설명에 나온것처럼 세팅을 해 줍니다.




실제 기능은 완료가 되었습니다. 아주 간단하죠.


이제 확인을 해보고 위해서 레이블 하나를 추가하겠습니다.


[NGUI] 버튼과 레이블 참고




ToggleHandler라는 스크립트를 하나 만들고, 


다음 처럼 코딩하겠습니다. (설명은 주석으로 하겠습니다)



< ToggleHandler.cs 코드 >


using UnityEngine;
using System.Collections;

public class ToggleHandler : MonoBehaviour {

    // 어떤 버튼이 활성화 되었는지 표시하기 위함.
    public UILabel m_lblMessage;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}

    // 토글 버튼이 바뀔 때 발생하는 이벤트
    public void OnChangeToggle()
    {
        // 현재 상태가 변한 토글버튼을 가져옵니다.
        UIToggle current = UIToggle.current;
        // 우리는 활성화 된 경우만 처리할 예정이므로,
        // 활성화 된것(value가 true)이 아닌경우(false인 경우) return합니다.
        if (current.value == false) return;
        // 확인을 위해 메시지를 뿌립니다.
        m_lblMessage.text = current.name;
    }
}



코드 작성이 완료되었으면, 


ToggleHandler.cs를 UI Root 게임 오브젝트에 넣어줍니다.




메시지를 봐야하므로, Message를 연결시켜줍니다.




마지막 단계만 남았습니다.


ToggleA(Gray)를 선택하보면, 아까 넣어둔 UIToggle이 보입니다.


거기에 보면 On Value Change라는게 보이는데, 


상태가 변하면 발생하는 이벤트 입니다.


우리가 만든 함수를 거기에 등록하도록 하겠습니다.




이제 실행을 하고 버튼을 눌러보면, 다음과 같은 결과를 볼 수 있습니다.



< 결과 >



기본 기능은 간단하지만, 


제어를 하려면 수작업이 좀 필요합니다.


다음 포스팅에는 제어하는 방법에 대해 설명하도록 하겠습니다.


궁금한 사항은 댓글달아주세요.



'게임 프로그래밍 > NGUI' 카테고리의 다른 글

[NGUI] 토글버튼(Toggle) 제어  (0) 2016.07.13
[NGUI] 버튼과 레이블  (0) 2016.06.07
[NGUI]스프라이트(SPRITE)  (0) 2016.05.26
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

C# CSV 파일 읽기(CSV Reader)



원래 XML을 사용하려고 했는데, 


읽는 속도가 CSV가 빠를것 같아서 간단히 구현을 하려합니다.


다음과 같은 데이터로 테스트를 하겠습니다.


ID앞에 #을 붙인 이유는 첫 라인이 키라는것을 명시하기 위함입니다.


* 파싱할 때 첫 라인을 키로 잡아도 됩니다.




만든 테이블을 CSV로 저장을 하였다면, 


인코딩을 UTF8로 바꿔주셔야 합니다.


그래야 모든 언어에서 오류없이 작동합니다.


자동 저장은 http://slway000.tistory.com/17 를 참고하세요.


우선 수작업으로 하기 위해, 메모장으로 열어서 다음처럼


인코딩을 UTF-8로 바꿔줍니다.




다음은 C#으로 작성한 코드 입니다. 


(테스트 코드를 만들고 나중에 유니티에 적용할 예정입니다.)


파일을 읽어들여 한라인씩 읽어서 


키와 값들을 구분시켜 처리하도록 합니다.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace CSVParse
{
    class Program
    {
        static void Main(string[] args)
        {
            string strFile= "testcsv.csv";

            using (FileStream fs = new FileStream(strFile, FileMode.Open))
            {
                using (StreamReader sr = new StreamReader(fs, Encoding.UTF8, false))
                {
                    string strLineValue = null;
                    string[] keys = null;
                    string[] values = null;

                    while ((strLineValue = sr.ReadLine()) != null)
                    {
                        // Must not be empty.
                        if (string.IsNullOrEmpty(strLineValue)) return;

                        if (strLineValue.Substring(0, 1).Equals("#"))
                        {
                            keys = strLineValue.Split(',');

                            keys[0] = keys[0].Replace("#", "");

                            Console.Write("Key : ");
                            // Output
                            for (int nIndex = 0; nIndex < keys.Length; nIndex++)
                            {
                                Console.Write(keys[nIndex]);
                                if (nIndex != keys.Length - 1)
                                    Console.Write(", ");
                            }

                            Console.WriteLine();

                            continue;
                        }

                        values = strLineValue.Split(',');

                        Console.Write("Value : ");
                        // Output
                        for (int nIndex = 0; nIndex < values.Length; nIndex++)
                        {
                            Console.Write(values[nIndex]);
                            if (nIndex != values.Length - 1)
                                Console.Write(", ");
                        }

                        Console.WriteLine();
                    }
                }                
            }            
        }
    }
}



결과화면입니다.




아주 간단한 예제이기 떄문에 실제 데이터 파싱할 경우


예외처리가 필요할 수 있습니다. 



336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

유니티3D 안드로이드(Android) 플러그인(Plugin) 만들기 Part 2.


안드로이드 스튜디오(Android Studio) 2.1.1 기준입니다.

 

* 안드로이드 스튜디오(Android Studio) 상위 버전 분들은 여기 를 눌러 확인바랍니다. *


 

* 유니티와 통신하는 방법은 몇가지가 있습니다.


그중 하나를 선택해서 테스트 하였습니다.


 참고 : http://docs.unity3d.com/Manual/PluginsForAndroid.html



유니티를 열고 새 프로젝트를 만듭니다.


그리고 Assets 및에 Plugins 라는 폴더를 만듭니다.


* 플러그인들은 무조껀 이 폴더에 있어야 합니다.


그리고 그 하위에 Android 폴더를 만듭니다.


* 각 플랫폼 별로 정해진 폴더를 사용해야 합니다.




Android의 플러그인을 사용하기 위해서는


Manifest파일을 적용시켜줘야 합니다.


Part1에서 만든 Manifest를 가져오기 위하여, 


다음 폴더에 가서 복사를 합니다.




그리고 Part 1에서 만든 플러그인(.Jar파일)과 


Manifest파일을 해당 폴더에 넣어줍니다.




여기에서 중요한 점은 Bundle Identifier를 맞춰주어야 합니다.


우리는 이전 패키지 이름을 


com.test.plugintest로 만들었기 때문에, 동일하게 적어주겟습니다.


(해당 Identifier로 Jar파일의 패키지를 읽어들이기 때문에 맞춰주어야 합니다)




다음은 저의 AndroidManifest.xml 파일입니다.


혹시 모르니 비교해보시기 바랍니다.




이제 중간 과정은 끝났으니, 실제 코드로 연동을 하겠습니다.


주석으로 설명 달아두었으니 참고하시기 바랍니다.


< PluginTest.cs 코드 >


using UnityEngine;
using System.Collections;

public class PluginTest : MonoBehaviour {

    string messge = "init";
    AndroidJavaClass myCls;
    AndroidJavaObject myObj;

    //// Use this for initialization
	void Start () {
        // 새로룬 오브젝트를 만들지 않고, com.unity3d.player.UnityPlayer의 
        // static 멤버에 접근하기 위해 AndroidJavaClass를 사용한다.
        // (사실 Android UnityPlayer가 자동으로 인스턴스를 생성해준다)
        myCls = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        // 그리고 static 필드인 currentActivity를 접근한다.
        // 그리고 이경우 AndroidJavaObject를 사용한다. 
        // 이유는 실제 필드 타입이 android.app.Activity이고
        // 이건 java.lang.Object를 상속받는다. 
        // 그리고, non-primitive 타입은 무조껀 AndroidJavaObject로 접근해야한다.
        // 예외 : strings.
        myObj = myCls.GetStatic("currentActivity");        
	}
    void OnGUI()
    {
        // 이렇게 접근하는 방법은, static이나 non-static 모두
        // 동일한 방법으로 접근 가능하다
        if (GUI.Button(new Rect(100, 100, 100, 50), "StaticInt"))
        {   
            messge += ("\n" + myObj.CallStatic("GetStaticInt", 123).ToString());
        }

        if (GUI.Button(new Rect(100, 200, 100, 50), "StaticString"))
        {
            messge += ("\n" + myObj.CallStatic("GetStaticString", "StaticString"));
        }

        if (GUI.Button(new Rect(100, 300, 100, 50), "Int"))
        {
            messge += ("\n" + myObj.Call("GetInt", 456).ToString());
        }

        if (GUI.Button(new Rect(100, 400, 100, 50), "String"))
        {
            messge += ("\n" + myObj.Call("GetString", "String"));
        }
      
        GUI.Label(new Rect(Screen.width / 2 - 350, Screen.height / 2 - 150, 700, 300), messge);
    }
}



< 결과 화면 >




처음에도 말했듯이 연동방법에는 몇가지가 있습니다.


자신이 편한걸로 하면 되지 않을까하네요.


그리고 문서를 보니 통신하는게 부하가 많이 발생한다고 합니다.


가능하면 최적의 호출로 해야겠네요.


도움되셧길 바랍니다.



* 플러그인만들기 추가



336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

유니티3D 안드로이드(Android) 플러그인(Plugin) 만들기 Part 1. 

안드로이드 스튜디오(Android Studio) 2.1.1 기준입니다.

 

* 안드로이드 스튜디오(Android Studio) 상위 버전 분들은 여기 를 눌러 확인바랍니다. *


 

* 이 글을 보시는 분들은 필수적으로

Android Studio 2.1.x가 설치되어 있어야 합니다.

또한 개인적으로 구글링한 방법이니 참고만 하시기 바랍니다.



안드로이드 스튜디오(Android Studio)를 실행하여 New Project를 합니다.


Application name과 Company Domain을 써줍니다.


저는 다음처럼 하겠습니다.




그리고 Next를 누르게 되면 다음과 같은 화면이 나옵니다.


저는 Phone과 Tablet에서 실행 하므로 다음처럼하였습니다.


그리고 Minimum SDK는 각 상황에 맞도록 설정하면 됩니다.




그리고 Next를 누르면 Activity 설정이 나오는데 


Empty Activity로 지정해 줍니다. 그리고 Next를 눌러줍니다.




Generate Layout File은 체크 해제 하겠습니다.


(필요 없을 것 같네요)


그리고 Finish를 눌러 세팅을 완료합니다.




프로젝트가 생성되었습니다.


이제 할 일은 Unity에서 사용할 수 있도록 classes.jar를 추가해야 합니다.


최상위 app에서 마우스 오른쪽을 눌러서 Open Module Settings를 들어갑니다.


(메뉴를 통해서도 가능합니다)




그리고 Dependencies 탭으로 이동하고, 


우측에 + 버튼을 눌른 후 File dependency를 선택합니다.




그럼 다음과 같은 화면을 보실 수 있습니다.


libs를 선택하면 상위에 경로가 나타나는데,  복사를 해 둡니다.


그리고 윈도우 탐색기(단축키 : 윈도우 + E)로 들어가서 


경로를 복사해 해당 폴더를 활성화 해 둡니다.




이제 유니티가 가지고 있는 classes.jar 파일을 


좀전에 열어둔 폴더로 옮겨야 합니다.


일반적으로 설치를 하셨다면 다음 그림에 보이는 경로에 있는 것입니다.




복사를 해서 아까 열어둔 폴더로 


classes.jar 파일을 복사합니다.




그리고 화면을 보시면 방금 추가한 파일이 나타납니다.


OK를 눌러줍니다.




잘 들어갔는지 확인을 하고 


OK를 눌러줍니다.




이제 불필요한 파일들을 지우겠습니다.


프로젝트쪽을 보시면 아래와 같이 test라는 것들이있습니다.


불필요 하므로 모두 삭제하겠습니다.




이제 유니티에서 호출할 테스트 코드를 작성하겠습니다.


MainActivity.java 파일로 들어갑니다.


우리는 UnityPlayerActivity를 상속 받아야 합니다.  다음 그림처럼 상속을 받아 줍니다.


그리고 static함수와 일반 함수를 호출 하는 함수들을 만들었습니다.



< 코드 >


 package com.test.plugintest;


import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {
// Call Static function
public static int GetStaticInt(int a)
{
return a + a;
}

public static String GetStaticString(String str)
{
return "Static GetString() : " + str;
}

public int GetInt(int a)
{
return a + a;
}

public String GetString(String str)
{
return "GetString() : " + str;
}
}



함수추가까지 완료되었습니다.


이제 남은일은 지금까지 만들었던 것들을 


jar 파일로 만들어서 유니티 쪽에 넣어주는 일입니다.


Gradle Scripts를 보시면 build.gradle(Module:app)이 있습니다. 더블클릭을 합니다.


그러면 다음과 같은 코드들을 볼 수 있습니다.



< 코드 >


apply plugin: 'com.android.library'

android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
//applicationId "com.test.plugintest"
minSdkVersion 10
targetSdkVersion 23
// versionCode 1
// versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.4.0'
compile files('libs/classes.jar')
}

task deleteObjectJar(type: Delete){
delete 'release/AndroidPlugin.jar'
}

task exportJar(type: Copy){
from('build/intermediates/bundles/release/')
into('release/')
include('classes.jar')
rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteObjectJar, build)



그 코드들을 다음처럼 수정합니다.

(참고 : http://www.thegamecontriver.com/2015/04/android-plugin-unity-android-studio.html)




모두 작성이 되었으면, 메뉴에 Build ->Clean Project를 해 줍니다.




그리고 Gradle projects를 보시면 app->Tasks->other 쪽에


exportJar가 보일 것입니다.(좀전에 Gradle에 선언한 이름)




더블 클릭을 하시게 되면, 


Jar파일을 만드는 로그를 보실 수 있습니다.




확인을 위해 Project에서 app을 선택하고, 


우측 클릭을 하고 Show in Explorer를 선택합니다.




그리고 프로젝트 폴더에 app/release를 가시면 


방금 생성한 Jar파일이 보이실 것입니다.



여기까지 Android Studio를 통해 Jar파일 만드는 법을 하였습니다.


다음에는 실제 Jar파일을 읽어들여 유니티와 통신하는 방법을 포스팅 하겠습니다.


질문 있으시면 댓글 달아주세요.


336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

패키지 파일입니다. 다운받으세요^^

pack.unitypackage


[ 유니티허브 질문 ] 유니티 리소스 로드 하기. (cho3**** 님)



다음 순서를 통해 설명드리겠습니다.

1. 프리팹 만들기.

2. 스크립트 만들기.

3. 스크립트 등록하기.

4. 스크립트를 통해 로드하기.

5. 테스트.



우선 테스트를 할 프리팹 하나를 만들도록 하겠습니다.


큐브를 하나 만들어서 사용할게요.


아래 그림에 나타난 방법중 하나를 선택하여 하시면 되십니다.




그러면 큐브가 하나 만들어 졌습니다.


이제 이 큐브를 프리팹으로 만들도록 하겠습니다.




Project 쪽을 모시면 Assets라는 폴더만 있을것입니다.


그 하위로 마우스 오른쪽 눌러서 폴더를 만드는데


이름을 꼭!!! Resources 라고 해주셔야 합니다.


(이유가 궁금하시면 댓글달아주세요 ㅎㅎ)




이제 조금전에 만든 Cube를 Resources 폴더 내에 


쭉 끌어다 놓습니다.


그러면 Hierarchy쪽에 있는 Cube가 파란색으로 변합니다.


파란색이라는 건 프리팹이 되었다는걸 의미합니다.




이제 Hierarchy 쪽에 Cube를 지워줍니다.


그럼 다음 그림처럼 되었겠죠?




이제 스크립트를 만들어서 리소스를 로드하는 걸 하겠습니다.


우선 스크립트를 만들어야 합니다.


아래 그림의 방법중 하나를 골라서 스크립트를 만듭니다.




스크립트 이름은 LoadResource 라고 하겠습니다.


(스크립트는 어떤 폴더에 있건 상관없습니다.)




구현 코드 입니다. 코드에 주석을 달아두었으니 참고하시고


궁금한건 댓글 달아주세요. 


< LoadResource.cs 의 코드 >

using UnityEngine;
using System.Collections;

public class LoadResource : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        // A 키를 눌러 확인하겠습니다.
	    if(Input.GetKeyDown(KeyCode.A))
        {
            // Resources 폴더에 있는 것중, Cube라는 프리팹(게임오브젝트)를
            // 로드합니다. 원본이 로드되는것입니다.
            GameObject gObjPrefab = Resources.Load("Cube") as GameObject;

            // 혹시 파일이 없을 수도 있으니 null체크(로드가 안되면 null입니다).
            if (gObjPrefab != null)
            {
                // Instantiate 함수는 게임오브젝트를 복사해서 생성하는 역할을 합니다.
                Instantiate(gObjPrefab);
            }
        }
	}
}



코드가 완성 되었으면, 이 코드가 작동할 수 있도록 해야합니다.


그러기 위해서는 Hierarchy에 있는 게임오브젝트에


추가가 되어야 합니다. 


다음 그림처럼 LoadResource 스크립트를 끌어다가 Main Camera에 넣어주세요.


( Main Camera 뿐 아니라 Directional Light에 넣으셔도 됩니다. )


아래 그림에 Inspector보이시나요?


거기에 LoadResource 가 추가된것이 보입니다.




모든 작업이 끝났습니다.


실행을 하면 아래 왼쪽 그림처럼 아무것도 없을 거에요.


그리고 A 키를 누르면 Cube(Clone)이 나타났을 것입니다.



최대한 자세히 설명했는데 이해가 되셨을지 모르겠네요.


궁금한건 언제든 물어보세요. 



*********** 추가 ********


리소스 폴더 내 파일 가져오기.


using UnityEngine;
using System.Collections;

public class LoadAllTest : MonoBehaviour {

	// Use this for initialization
	void Start () {

        //object[] obj = Resources.LoadAll("");     // Resources 폴더 내 모든 파일 가져오기
        object[] obj = Resources.LoadAll("Images"); // Resources/Images 폴더 내 모든파일 가져오기.
        for (int nIndex = 0; nIndex < obj.Length; nIndex++)
        {
            Debug.Log("Index : " + nIndex.ToString() + ", Object : " + obj[nIndex].ToString());
        }

    }
	
	// Update is called once per frame
	void Update () {
	
	}
}


모든 파일을 가져오니 타입이나 확장자를 통해서


구분을 하셔야 합니다 ㅎㅎ



********** 추가 ********


조원희 님이 원하시는 소스.


(제가 이해한게 맞길 바래요)


using UnityEngine;
using System.Collections;

public class LoadResource : MonoBehaviour {

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {
        // A 키를 눌러 확인하겠습니다.
	    if(Input.GetKeyDown(KeyCode.A))
        {
            GameObject cube = null;
            // Resources 폴더에 있는 것중, Cube라는 프리팹(게임오브젝트)를
            // 로드합니다. 원본이 로드되는것입니다.
            GameObject gObjPrefab = Resources.Load("Cube") as GameObject;

            // 혹시 파일이 없을 수도 있으니 null체크(로드가 안되면 null입니다).
            if (gObjPrefab != null)
            {
                // Instantiate 함수는 게임오브젝트를 복사해서 생성하는 역할을 합니다.
                cube = Instantiate(gObjPrefab);
            }

            // 모든 리소스 불러오기(Image 폴더내에 입니다)
            // 현재 Image 폴더내에는 Texture만 있으므로 분류처리 안할께요.
            // 분류처리(?)란 Image 폴더내에 프리팹이나 사운드 파일 등이 같이 있을 때에
            // 텍스쳐만 가져오도록 하는 것입니다. 
            // 궁금하시면 말씀하세요. 다시 알려드릴께요^^
            // 우런 아래처럼 LoadAll을 하시면 Image 폴더안에 있는
            // 모든 이미지들(사실은 오브젝트)이 배열이라는 걸로 저장됩니다.
            // [] <= 요게 배열.
            object[] arrObj = Resources.LoadAll("Images");

            // 그래서 배열에서 첫번째껄로(0부터 시작합니다) 세팅하도록 할께요.
            // 그리고 지금은 무조껀 텍스처라고 가정하므로 이렇게 형변환 이라는걸 해줘야 되요.
            Texture2D texture = arrObj[0] as Texture2D;
            // 텍스쳐(이미지)를 가져왔으니 큐브에 세팅~!.
            cube.GetComponent().material.mainTexture = texture;
            
        }
	}
}


* 소스에서 가장 아래 </Renderer> 이거는 삭제하세요.


* 소스 코드 올리는거에 약간 버그같은거? 가 있어서 ㅎㅎ


위쪽에서 스크립트 등록하는거 보셨죠?


그렇게 똑같이 등록해서


실행한 다음에 A 키 눌러보세요.


그러면 이렇게 세팅.



메일 주소 적어주세요. 


완성된 프로젝트 보내드릴께요.


(저는 버전 5.3.5 사용중입니다)


******* 실시간으로이미지 로딩하기 추가. ******


테스트 해보니 잘 되네요.


현재 테스트 용이므로, 실제 원하시는 기능은 다시 구현하셔야 되세요 ㅎㅎ

이미지는 여기꺼 : http://www.flaticon.com/packs


코드에 주석 달아두었습니다.



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

public class LoadResources : MonoBehaviour {

    // 생성된 큐브를 화면내에 뿌리기 위해 최대치 지정.
    private readonly float MIN_X_POS = -8f;
    private readonly float MAX_X_POS = 8f;
    private readonly float MIN_Y_POS = -4f;
    private readonly float MAX_Y_POS = 4f;

    // 현재까지 만들어진 것 저장. 중복해서 생성하지 않기 위해 만듬.
    List m_lImageNames = new List();
    // 1초에 한번씩 검사.
    float m_fTimeChecker = 0f;
    // 큐브 프리팹.(한번 로드해 두고 복사해서 생성한다)-> 속도 위함.
    GameObject m_gObjCubePrefab;
	// Use this for initialization
	void Start () {
        m_gObjCubePrefab = Resources.Load("Cube") as GameObject;
        // 로드 실패할 경우를 대비하여 Null 체크 해본다.
        if (m_gObjCubePrefab == null)
        {
            Debug.LogError("Can not load cube!! Please check the path of the cube!");
        }

	}
	
	// Update is called once per frame
	void Update () {
        LoadImagesDynamically();
	}

    // 1초에 한번씩 검사해서 로드하지 않은 이미지들 로드해서 보여주기.
    // 큐브를 생성하여 이미지를 표시한다.
    private void LoadImagesDynamically()
    {
        // 큐브프리팹이 null이면 안된다!!
        if (m_gObjCubePrefab == null) return;

        // 경과 시간을 계산한다.
        m_fTimeChecker += Time.deltaTime;

        // 1초마다 생성.
        if (m_fTimeChecker >= 1f)
        {
            // 경과시간 초기화.
            m_fTimeChecker = 0f;

            // 우선 이미지들 로드 후 검사.
            object[] arrObj = Resources.LoadAll("Images");

            for(int nIndex =0 ;nIndex < arrObj.Length; nIndex++)
            {
                Texture2D texture = arrObj[nIndex] as Texture2D;

                if (texture != null)
                {
                    // 기존에 로드 했는지 검사 후 신규일 경우만 생성.
                    if (IsAlradyLoaded(texture.name) == false)
                    {
                        // 로드한 리스트에 이름 추가(중복 로드 피하기 위해서)
                        m_lImageNames.Add(texture.name);
                        // 새로 큐브 생성.
                        GameObject gObjNew = Instantiate(m_gObjCubePrefab) as GameObject;
                        // 큐브 위치 랜덤하게 잡고.
                        gObjNew.transform.localPosition = GetRandomPosition();
                        // 이미지 세팅하도록 한다.
                        gObjNew.GetComponent().material.mainTexture = texture;
                    }
                }
            }            
        }
    }

    // 기존에 이미 로드된 것인지 검사하는 함수
    // 이미 로드되었으면 true를 리턴한다. 그렇지 않으면 false 리턴.
    private bool IsAlradyLoaded(string _str)
    {
        for (int nIndex = 0; nIndex < m_lImageNames.Count; nIndex++)
        {
            if (m_lImageNames[nIndex] == _str)
                return true;
        }

        return false;
    }

    // 랜덤으로 위치 얻기.
    private Vector3 GetRandomPosition()
    {
        float x = Random.RandomRange(MIN_X_POS, MAX_X_POS);
        float y = Random.RandomRange(MIN_Y_POS, MAX_Y_POS);
        // z축은 하지 않을께요 ㅎㅎ

        return new Vector3(x, y, 0f);
    }
}


가장 아래 </renderer></string></string>은 지워주세요.




336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.



- 유니티 버전 : 5.3.4f -



유니티3D 에디터(Editor) 캐시 삭제하기(Clean Cache)


어셋번들 매니저를 만들면서 테스트 하는데, 


단축키로 캐시삭제(Caching.CleanCache)를 하는데 불편함을 느껴서


에디터로 옮겼습니다.


*참고 : 캐시 삭제하는 함수는 Caching.CleanCache()입니다.


1분 작업량에 비해 많이 편하네요. 


우선 메뉴가 잘 만들어 졌는지 확인을 하겠습니다.


CleanCache라고 제가 만들어논 메뉴가 보이네요.




메뉴를 선택해보니 


오류없이 삭제되었다는 알림이 나왔습니다.




이제 정말 캐시가 삭제되었는지 확인을 해봐야 겠네요.


참고로 저는 지금 임시 UI로 


패치시스템을 만들고 있는 중입니다. (아주 간단하게..)


게임 실행을 해보니 13개 파일 받을게 있네요.




잘 받아지는지도 확인 해 보겠습니다.


13개가 차례대로 잘 받아집니다.




< 에디터 코드 >

using UnityEngine;
using UnityEditor;
using System.Collections;

public class PedtClearCaching {

    [MenuItem("Util/CleanCache")]
    public static void CleanCache()
    {
        if(Caching.CleanCache())
        {
            EditorUtility.DisplayDialog("알림", "캐시가 삭제되었습니다.", "확인");
        }
        else
        {
            EditorUtility.DisplayDialog("오류", "캐시 삭제에 실패했습니다.", "확인");
        }
    }
}


성공여부에 따라 팝업을 하나 띄워두었습니다.


Caching.CleanCache가 실패하는 경우는 


캐시를 사용하고 있을 때 입니다. 


혹시 실패가 뜬다면 유니티를 다시 껐다가 다시 켜보세요.


도움되셨길 바랍니다.

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.



- 유니티 버전 : 5.3.4f -



니티3D 에디터(Editor) 하위 폴더 순회하기(Recursion)


특정 폴더가 있고 그 하위 게임오브젝트에 어떠한 스크립트를 추가 할 일이 생겼습니다.


그런데 너무 많다보니 수작업으로는 안되겠더라구요.


그래서 에디터를 이용해서 추가하였습니다.


(실제 코드는 아래쪽에 작성하겠습니다.)


상단 메뉴로 Util을 만들고 하위에 두개의 메뉴를 만들었습니다.


하나는 스크립트 붙이는거, 다른 하나는 스크립트 제거하는거.




아래 그림에 있는 설명처럼 루트 폴더를 선택하고, 메뉴를 통해 스크립트를 붙여주면, 


프리팹 게임오브젝트에만 스크립트가 붙는걸 볼 수 있습니다.




다시 루트에서 제거하기 메뉴를 누르면


스크립트가 제거되는 걸 볼 수 있습니다.



< 에디터 코드 >


using UnityEditor;
using UnityEngine;
using System.Collections;
using System.IO;

public class PedtAutoAttachScript : Editor{
    [MenuItem("Util/AttachReApplyShaders")]
    public static void AttachReApplyShaders()
    {
        Object[] selectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

        foreach(Object obj in selectedAsset)
        {            
            GameObject gObj = obj as GameObject;
            if (gObj != null)
            {
                string str = AssetDatabase.GetAssetPath(gObj);
                // Skip FBX 
                string strExtension = Path.GetExtension(str);
                Debug.Log(strExtension);
                if (strExtension.ToLower().CompareTo(".prefab") == 0)
                {
                    // 이미 추가 되어있는지 검사.
                    PcAutoAttatch script = gObj.GetComponent();
                    if(script == null)
                    {
                        // 없으면 추가.
                        gObj.AddComponent();
                        Debug.Log("Asset name : " + obj.name + " Type : " + obj.GetType());
                    }                    
                }                
            }
        }
    }

    [MenuItem("Util/RemoveReApplyShaders")]
    public static void RemoveReApplyShaders()
    {
        Object[] selectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);

        foreach (Object obj in selectedAsset)
        {            
            GameObject gObj = obj as GameObject;
            if (gObj != null)
            {               
                PcAutoAttatch script = gObj.GetComponent();
                if (script != null)
                {
                    Debug.Log("Asset name : " + obj.name + " Type : " + obj.GetType());
                    DestroyImmediate(script, true);
                }
            }
        }
    }
	
}


에디터를 통해 자동화가 된다면 최대한 사용해야겠죠?


도움 되셨길 바랍니다.



+ Recent posts