2014년 3월 7일 금요일

Android 상에서의 Unity 개발을 위한 필요 사항(plugin 개발 방법, debugging) 링크 정리

Android 타겟으로 Unity 개발을 위한 개발 방법 링크를 정리함.
- Android plugin for Unity
- Rest API using in C# script
- tutorial links

[Plugin for Android]

대충 정리해 보면
Android 타겟으로 Unity로 게임 개발 시
Unity 내에서 안드로이드 feature를 사용할 수 없는 부분이 있음.
(예, billing, Android system feature 사용 등)

위 문제점을 해결하고자
Android native plugin을 개발해서 Android <-> Unity간 interaction을 만들어 처리해야 한다.

Android native plugin 내에서 사용 가능한 방법은
1. Unity JNI를 이용해서 Android feature를 사용하는 java method를 호출하는 방법
   : 반대로 Android side에서는 Unity에서 제공하는 UnityPlayer를 이용해 메세지를 보낼 수 있음.
2. UnityPlayerActivity를 상속받아 method를 override하여 처리하는 방법이 있음.

개발 결과물은
 - Unity에서 바로 Android phone으로 deploy할 수 있고
 - Android project로 export해서 eclipse에서 deploy할 수 있다.


Building Plugings for Android

Unity 공식 문서에서는 Android plugin에서 사용 가능한 두가지 방법을 설명하고 있음.
1. Using Java Plugins
 > Script상에서 JNI interface를 사용하여 java code를 직접 호출하여 사용 하는 방법

using UnityEngine; 
public class NewBehaviourScript : MonoBehaviour { 

 void Start () { 
  AndroidJNIHelper.debug = true; 
  using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { 
   jc.CallStatic("UnitySendMessage", "Main Camera", "JavaMessage", "whoowhoo"); 
  } 
 } 

 void JavaMessage(string message) { 
  Debug.Log("message from java: " + message); 
 }
} 

2. Extending the UnityPlayerActivity Java Code
 > UnityPlayerActivity를 상속 받아 Activity 코드에서 Android 관련 처리를 할 수 있도록 하는 방법

public class OverrideExample extends UnityPlayerActivity {

  protected void onCreate(Bundle savedInstanceState) {

    // call UnityPlayerActivity.onCreate()
    super.onCreate(savedInstanceState);

    // print debug message to logcat
    Log.d("OverrideActivity", "onCreate called!");
  }

  public void onBackPressed()
  {
    // instead of calling UnityPlayerActivity.onBackPressed() we just ignore the back button event
    // super.onBackPressed();
  }
} 
* 참고로 UnityPlayer에는 사용중인 Activity를 나타내는 currentActivity property와
  Unity로 메세지를 보낼 수 있는 UnitySendMessage method가 있어 참고 하면 될듯.
  (다른 것들 도 있으나 어디서 어떻게 사용해야 하는지 잘 모르겠음)


http://blog.naver.com/PostView.nhn?blogId=saram95&logNo=90176732890&parentCategoryNo=11&categoryNo=30&viewDate=&isShowPopularPosts=false&from=postView
: UnityPlayerActivity를 상속 받아 사용 하는 방법에 대한 자세한 설명

 - UnityPlayerActivity를 상속한 activity를 가진 Android Project 생성
 - library로 만든 후 jar 파일 생성 Unity project에 추가
 - Unity project에서 JNI를 통해 Android의 activity의 method 호출

http://www.devkorea.co.kr/bbs/board.php?bo_table=m03_lecture&wr_id=3369&sca=Unity3D&currentId=42
: Android in-app billing 추가 방법

http://it-backup.tistory.com/2
: Unity Project를 eclispe project로 Export하는 방법

[C# plugin for eclipse]

: eclipse용 C# plugin 'Emonic'이 존재

up vote14down voteaccepted
Emonic is an actual eclipse plugin for C#: http://emonic.sourceforge.net/.
Here's a handy guide for how to get it set up: http://www.ibm.com/developerworks/library/os-eclipse-migratenetvs/
Monodevelop is great, but won't meet your requirement not to have to work in multiple IDEs.
share|improve this answer

http://www.ibm.com/developerworks/library/os-eclipse-migratenetvs/
: 'Emonic'을 사용하여 .Net project를 컴파일 하는 방법을 설명
 => eclipse 용 C# plugin을 사용해서 Unity 프로젝트를 빌등 할 수 없는 것으로 보이니 안드로이드 개발자들은 그냥 참고만 하시라...




Krispy's Avatar
Location
Ontario
Posts
69

Eclipse, C#, and Unity

So, I've been trying to start using Eclipse (with the Emonic C# plugin) with Unity, mainly for ease of debugging, unit testing, and integration with code repositories. I'm still stumped on how I get Eclipse to use the UnityEngine namespace, or, more accurately, how to actually get the UnityEngine namespace.

Any help?


[Android debuging tip]

http://forum.unity3d.com/threads/70197-Any-tips-for-debugging-Android
: Android debugging tip

eriQue
Simply start it like this:


$ adb logcat

and it will start printing out everything that is going on on the device. To limit it to only show the output from inside Unity, you can try this:

$ adb logcat -s Unity

or, to get a little bit more info about what's going on:

$ adb logcat -s Unity ActivityManager PackageManager dalvikvm DEBUG

If you wish to report a bug or otherwise 'quote' the logcat, you can dump the complete logcat to a file like this:

$ adb logcat -d > logcat.txt


2014년 3월 6일 목요일

Android 상에서의 Unity 개발 환경 링크 정리

Unity를 Android 상에서 개발을 하려면 필요한 사항들을 정리함.

개발환경 중
OS는 Unity 개발 툴이 Windows, iOS를 지원하므로 Linux는 제외이고

관련 필요한 기본 개발 툴은
- Unity 개발 툴
 : C# script 편집 및 디버깅을 위해 Mono Develop을 포함 하고 있음.
- Android SDK, Java runtime

그 외 필요한 개발 툴은
- Visual Studio
 : C# script 편집을 위해 필요하다면, 단 express, pro 버전 별 사용 시 차이점 있음.
 : 단 편집만 가능.

- UnityVS
 : Visual Studio에서 Unity script 편집, 디버깅을 가능하게 해주는 plugin
 : 유로, 안 써봐서 모르겠지만 다른 포스팅들에서 추천함..


[Unity & Android]
Getting Started
: http://docs.unity3d.com/Documentation/Manual/android-GettingStarted.html
 > 별 내용은 없으나 하단에 링크 포함.


Page last updated: 2013-10-10
Unity 설치
: http://blog.naver.com/PostView.nhn?blogId=foxmann&logNo=90178254718

Unity Android에서 지원되지 않는 Feature들
: http://docs.unity3d.com/Documentation/Manual/android-unsupported.html

- Graphics
 : Non-square textures are not supported by the ETC format.
 : Movie Textures are not supported, use a full-screen streaming playback instead. Please see the Movie playback page for more information.
- Scripting
 : OnMouseEnter, OnMouseOver, OnMouseExit, OnMouseDown, OnMouseUp, and OnMouseDrag events are not supported on Android.
 : Dynamic features like Duck Typing are not supported. Use #pragma strict for your scripts to force the compiler to report dynamic features as errors.
 : Video streaming via WWW class is not supported.
Page last updated: 2012-10-08

Touble Shooting



[Unity Android 개발환경]

Android SDK Setup
: http://docs.unity3d.com/Documentation/Manual/android-sdksetup.html
 > 공식 방법, 좀 더 자세한 설명은 하단 링크 참조

1. Download the Android SDK

2. Installing the Android SDK
...In step 4 of Installing the SDK be sure to add at least one Android platform with API level equal to or higher than 9 (Platform 2.3 or greater), the Platform Tools, and the USB drivers if you're using Windows.

3. Get the device recognized by your system
...Note: Don't forget to turn on "USB Debugging" on your device. Go to Settings -> Developer options, then enable USB debugging. As of Android Jelly Bean 4.2 the Developer options are hidden by default. To enable them tap on Settings -> About Phone -> Build Version multiple times. Then you will be able to access the Settings -> Developer options.

4. Add the Android SDK path to Unity
The location of the Android SDK can also be changed in the editor by selecting Unity > Preferences from the menu and then clicking on External Tools in the preferences window.


http://blog.naver.com/PostView.nhn?blogId=saram95&logNo=90176731230&categoryNo=23&parentCategoryNo=11&viewDate&currentPage=1&postListTopCurrentPage=1
: Java 부터 안드로이드, Unity 개발 환경 구축, Plugin 개발을 상세히 정리함.
 > Android SDK
 > Unity Android SDK 설정
 > Android Plugin 만들기


http://phiru.tistory.com/164
: 좀 오래되긴 했지만 Android 설정 및 Unity 연동 관련 설명, 같은 카테고리에 unity 3D 관련 tip들이 정리되어 있음.

[Unity with VisualStudio]

http://docs.unity3d.com/Documentation/Manual/VisualStudioIntegration.html

Unity's VisualStudio integration has two components:
1) Unity creating and maintaining VisualStudio project files. Works with Express and with Profesional.
2) Unity automatically opening VisualStudio when you doubleclick on a script, or error in Unity. Works with Professional only.

I've got Visual Studio Express, how do I use it?

  • In Unity, select from the menu Assets->Sync MonoDevelop Project
  • Find the newly created .sln file in your Unity project (one folder up from your Assets folder)
  • Open that file with Visual Studio Express.
  • You can now edit all your script files, and switch back to Unity to use them.

I've got Visual Studio Profesional, how do I use it?

  • In Unity, go to Edit->Preferences, and make sure that Visual Studio is selected as your preferred external editor.
  • Doubleclick a C# file in your project. Visual Studio should automatically open that file for you.
  • You can edit the file, save, and switch back to Unity.

http://myevan.cpascal.net/articles/2013/unity_vs_gac_win7.html
: 설정 방법 및 빌드에러 조치법 포함.

하지만 Unity-MonoDevelop 과는 다르게 UnityEngine.dll 과 UnityEditor.dll 을 찾지 못해 빌드 에러가 발생합니다.프로젝트 참조 추가 기능을 사용해서 유니티 에셈블리 경로를 추가해주는 방법도 있지만, Sync MonoDevelop Project 를 설정할 때마다 참조를 추가해주어야 하는 불편함이 있습니다.
/Applications/Unity//Unity.app/Contents/Frameworks/Managed/
GAC(Global Assembly Cache) 기능을 사용하면 유니티 어셈블리를 빌트인 어셈블리처럼 사용할 수 있습니다.Windows 7 64bit 버전라면 레지스트리 에디터(regedit.exe)를 실행해 다음과 같은 내용을 추가합니다.
[HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft.NETFramework\AssemblyFolders]
유니티 프레임워크 어셈블리 dll 경로
mac+parallerls 를 사용하는 경우 /Application 경로에 직접 접근이 되지 않으므로 “C:\UnityFrameworks/버전"에 어셈블리 파일들을 복사해서 사용합니다.비주얼 스튜디오를 재실행하면 UnityEngine 과 UnityEditor 위에 표시된 느낌표(!)마크가 사라지면서 빌드를 할 수 있게 됩니다.
참고 자료

UnityVS - plugin

: http://devkorea.co.kr/bbs/board.php?bo_table=m03_qna&wr_id=25504
: http://directaccess.tistory.com/entry/UnityVS-12-VisualStudio-2012

 => Visual Studio에서 편집만 할 것면 상관 없지만 디버깅이 필요하다면 필요.
단지 Visual Studio를 C# 편집기로 사용한다면 답답하기 짝이 없다. 그냥 텍스트 편집기일 뿐이고 컴파일이나 디버깅을 할 수 없고 Unity에서 사용되는 asset을 접근할 수 도 없음...
UnityVS를 사용해 본적은 없지만 Unity에서 사용하는 project setting을 그대로 구성해 주고 디버깅도 가능하다고 하니... 한번 사용해보고 싶다..


eclipse as Unity C# editor

http://forum.unity3d.com/threads/6558-Eclipse-C-and-Unity
: eclipse에서 C# plugin인 Emonic을 사용해서 Unity와 연동 개발 시 문제를 해결 방법을 묻고 있지만 이래저래 하다 좀 엉뚱하게 Visual Sutdio plugin을 소개하는 답이 달리게 됨.
 > C# script 편집, 컴파일 위한 Unity와 eclipse의 연동 개발은 어려운 것으로 보임.

질문 >

Krispy's Avatar
Location
Ontario
Posts
69

Eclipse, C#, and Unity

So, I've been trying to start using Eclipse (with the Emonic C# plugin) with Unity, mainly for ease of debugging, unit testing, and integration with code repositories. I'm still stumped on how I get Eclipse to use the UnityEngine namespace, or, more accurately, how to actually get the UnityEngine namespace.

Any help?

[MonoDevelop 디버깅 방법]

: http://adolys.tistory.com/entry/Unity3D-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Debugging-%EA%B4%80%EB%A0%A8-%ED%8C%81



2014년 2월 27일 목요일

Android multicast packet send, receive

Android에서 multicast packet 전송, 수신을 다룰 때 특별한 권한 및 유의 사항이 있음.

[Multicast sending]

- DatagramSocket을 사용 (broadcast 설정, 올바른 port 설정)

channel = DatagramChannel.open();
channel.socket().setReuseAddress(true);
channel.socket().setBroadcast(true);
channel.socket().setSendBufferSize(UDP_BUFFER_SIZE);

- 올바른 주소로 DatagramPacket 전송
  : wifiap (hotspot)일 경우 broadcast 주소(interface info에 있는)로 전송
  : 그 외 multicast 주소로 전송

아래 [multicast sending, receiving mini sample] 참고


[Multicast receiving]

- WifiManager.MulticastLock 설정 및 CHANGE_WIFI_MULTICAST_STATE permission

아래 [multicast 수신 설정] 참고

- MulticastSocket 사용 및 올바른 그룹주소와 interface에 대해 joinGroup()

InetSocketAddress socketAddress = new InetSocketAddress(addr, port);
socket = new MulticastSocket(port);
socket.setReceiveBufferSize(bufsize);

Enumeration<NetworkInterface> ifs = NetworkInterface.getNetworkInterfaces();

while (ifs.hasMoreElements()) {
  NetworkInterface xface = ifs.nextElement();
  Enumeration<InetAddress> addrs = xface.getInetAddresses();
  String name = xface.getName();

  if (false == name.startsWith("wlan")) {
  continue;
}

Log.e(LOG_TAG, "Listener Adding " + name + " to our interface set");
socket.joinGroup(socketAddress, xface);



참고 링크들

[multicast 사용 시 주의 점 및 address 지정 내용]
: https://plus.google.com/+Chainfire/posts/9NMemrKYnCd

To receive multicasts you need to do the following:
- use a MulticastSocket instead of a DatagramSocket
- MulticastSocket::joinGroup() the correct group
- hold a WifiManager.MulticastLock
- have the CHANGE_WIFI_MULTICAST_STATE permission

- Cell data and Wi-Fi connected: 255.255.255.255 works
- Cell data and Wi-Fi in hotspot mode: 255.255.255.255 works
- only Wi-Fi in hotspot mode: 255.255.255.255 doesn't work, throws network unreachable exception. Using the correct broadcast address works fine.



[multicast 수신 설정]
: http://codeisland.org/2012/udp-multicast-on-android/

Acquiring a lock
Actually getting the required lock isn’t that much trouble at all. Given that you declared your application to use the following permissions:

<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>

The code-part is as short as:

WifiManager wifi = (WifiManager)getSystemService( Context.WIFI_SERVICE );
if(wifi != null){
    WifiManager.MulticastLock lock = wifi.createMulticastLock("Log_Tag");
    lock.acquire();
}

[WifiManager.MulticastLock]
: http://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html

Allows an application to receive Wifi Multicast packets. Normally the Wifi stack filters out packets not explicitly addressed to this device. Acquring a MulticastLock will cause the stack to receive packets addressed to multicast addresses. Processing these extra packets can cause a noticable battery drain and should be disabled when not needed.


[multicast sending, receiving mini sample]
: https://code.google.com/p/boxeeremote/wiki/AndroidUDP

Getting the Broadcast Address

You need to access the wifi manager to get the DHCP info and construct a broadcast address from that:
InetAddress getBroadcastAddress() throws IOException {
    WifiManager wifi = mContext.getSystemService(Context.WIFI_SERVICE);
    DhcpInfo dhcp = wifi.getDhcpInfo();
    // handle null somehow

    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
      quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
}


* 근데 하다 보니 DhcpInfo 의 값이 모두 0인 경우가 있어서
interface 정보에서 broadcast 주소 획득하여 사용.

List<InterfaceAddress> addrs = xface.getInterfaceAddresses();String name = xface.getName();

if (false == name.startsWith("wlan")) { continue;}

for(InterfaceAddress addr : addrs){ if(addr.getAddress() instanceof Inet6Address){ continue;} Log.d(LOG_TAG, name + " has addr " + addr.getBroadcast());}



Sending and Receiving UDP Broadcast Packets

Having constructed the broadcast address, things work as normal. The following code would send the string data over broadcast and then wait for a response:
DatagramSocket socket = new DatagramSocket(PORT);
socket.setBroadcast(true);
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
    getBroadcastAddress(), DISCOVERY_PORT);
socket.send(packet);
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);

[broadcast 주소 획득]
: http://stackoverflow.com/questions/15524593/broadcasting-over-wi-fi-direct

Try getting you network connection this way:
InetAddress getBroadcastAddress() throws IOException {
    WifiManager wifi = mContext.getSystemService(Context.WIFI_SERVICE);
    DhcpInfo dhcp = wifi.getDhcpInfo();
    // handle null somehow

    int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
    byte[] quads = new byte[4];
    for (int k = 0; k < 4; k++)
      quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
    return InetAddress.getByAddress(quads);
}  
Then try sending a packet this way:
DatagramSocket socket = new DatagramSocket(PORT);
socket.setBroadcast(true);
DatagramPacket packet = new DatagramPacket(data.getBytes(), data.length(),
    getBroadcastAddress(), PORT);
socket.send(packet);

// If you want to listen for a response ...
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
Edit: From same page to read try this ...
WifiManager wifi = (WifiManager) this.getSystemService(Context.WIFI_SERVICE);
MulticastLock lock = wifi.createMulticastLock("dk.aboaya.pingpong");
lock.acquire();
serverSocket = new DatagramSocket(19876);
serverSocket.setSoTimeout(15000); //15 sec wait for the client to connect
byte[] data = new byte[UDPBatPositionUpdater.secretWord.length()]; 
DatagramPacket packet = new DatagramPacket(data, data.length);
serverSocket.receive(packet);
lock.release();
String s = new String(packet.getData());
System.out.println(s);
Remember, that you need the following permission for it to work:
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
share|improve this answer