Category Archives: Programming

[Unity3D] Spine importing with TK2D(2DToolkit)


Spine importing with TK2D

2DToolkit 에서 Spine애니메이션 가져오기

1. Spine 에서 Json 파일을 Export 한다.

2. Spine Runtime 중 Spine-Csharp 과 Spine- tk2d 을 유니티 Assets 안에 추가한다.(폴더 상관없음)

3. Spine 에서 애니메이션을 만들때 사용한 이미지들을 그대로 가져와 tk2d Sprite Collection을 만든다.

4.Json 파일과  Sprite Collection 파일을 동시에 선택 후

우클릭 – Create – Spine – Skeletondata form Selection  를 선택하면

Skeletondata가 생성된다.

5.  SkeletonData 를 우클릭 – Spine – Spawn 하면 SkeletonAnimation Object가 생성된다.







[Unity3D] TimeScale 의 영향을 받지 않는 particale

파티클은 유니티 엔진에서 컨트롤을 하기 때문에

TimeScale 이 0인 경우에는 동작하지 않는다.

이를 해결 하려면 다음 스크립트를 파티클 오브젝트에 추가한다.



using UnityEngine;
using System.Collections;

public class ParticaleAnimator : MonoBehaviour

    private void Awake()
        particle = GetComponent<ParticleSystem>();

    // Use this for initialization
    void Start()
        lastTime = Time.realtimeSinceStartup;

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

        float deltaTime = Time.realtimeSinceStartup - (float)lastTime;

        particle.Simulate(deltaTime, true, false); //last must be false!!

        lastTime = Time.realtimeSinceStartup;

    private double lastTime;
    private ParticleSystem particle;


[VS2013] CRLF/ LF 개행문자 자동 변환

비주얼 스크립트로 작성된 코드를 유니티에 적용하면 콘솔창에 경고가 보이는 경우가 있다.

이 이유는 유니티의 모노디벨롭은 유닉스 기반이라 개행 문자를 LF 방식을 사용하는데 반해

VS는 CRLF 방식을 사용하기 때문이다.

이것을 해결해주는 간단한 플러그인이 있어서 소개하본다.

사용법과 설명은 링크 참고.

물론 영어.. ㄷㄷㄷㄷ

그림대로만 따라하면 되고



You can download the Add-in and the source code separately:
 Add-in only – installer for VS 2013 (thanks to Turing Eret), Source code
 Add-in only – installer for VS 2012 (and 2010), Source code
 Add-in only – installer for VS 2008installer for VS 2010 (older version), Source code
 Add-in only – for VS 6Source code


여기서 Add-in only 를 클릭하면 된다.

설치는 더블클릭.



Android – BLE Scan Example


import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;

public class DeviceScanActivity extends ListActivity {
private LeDeviceListAdapter mLeDeviceListAdapter;
private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler;

private static final int REQUEST_ENABLE_BT = 1;
// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 10000;

public void onCreate(Bundle savedInstanceState) {
    mHandler = new Handler();

    // Use this check to determine whether BLE is supported on the device.  Then you can
    // selectively disable BLE-related features.
    if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
        Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
    // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to
    // BluetoothAdapter through BluetoothManager.
    final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = bluetoothManager.getAdapter();
    // Checks if Bluetooth is supported on the device.
    if (mBluetoothAdapter == null) {
        Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();

public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(, menu);
    if (!mScanning) {
    } else {
    return true;

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    return true;

protected void onResume() {
    // Ensures Bluetooth is enabled on the device.  If Bluetooth is not currently enabled,
    // fire an intent to display a dialog asking the user to grant permission to enable it.
    if (!mBluetoothAdapter.isEnabled()) {
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    // Initializes list view adapter.
    mLeDeviceListAdapter = new LeDeviceListAdapter();

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // User chose not to enable Bluetooth.
    if (requestCode == REQUEST_ENABLE_BT &amp;&amp; resultCode == Activity.RESULT_CANCELED) {
    super.onActivityResult(requestCode, resultCode, data);

protected void onPause() {

private void scanLeDevice(final boolean enable) {
    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable() {
            public void run() {
                mScanning = false;
        }, SCAN_PERIOD);
        mScanning = true;
    } else {
        mScanning = false;

// Adapter for holding devices found through scanning.
private class LeDeviceListAdapter extends BaseAdapter {
    private ArrayList&lt;BluetoothDevice&gt; mLeDevices;
    private LayoutInflater mInflator;

    public LeDeviceListAdapter() {
        mLeDevices = new ArrayList&lt;BluetoothDevice&gt;();
        mInflator = DeviceScanActivity.this.getLayoutInflater();

    public void addDevice(BluetoothDevice device) {
        if(!mLeDevices.contains(device)) {

    public BluetoothDevice getDevice(int position) {
        return mLeDevices.get(position);

    public void clear() {

    public int getCount() {
        return mLeDevices.size();

    public Object getItem(int i) {
        return mLeDevices.get(i);

    public long getItemId(int i) {
        return i;

    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;
        // General ListView optimization code.
        if (view == null) {
            view = mInflator.inflate(R.layout.listitem_device, null);
            viewHolder = new ViewHolder();
            viewHolder.deviceAddress = (TextView) view.findViewById(;
            viewHolder.deviceName = (TextView) view.findViewById(;
        } else {
            viewHolder = (ViewHolder) view.getTag();

        BluetoothDevice device = mLeDevices.get(i);
        final String deviceName = device.getName();
        if (deviceName != null &amp;&amp; deviceName.length() &gt; 0)

        return view;

// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =
        new BluetoothAdapter.LeScanCallback() {

    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
        runOnUiThread(new Runnable() {
            public void run() {

static class ViewHolder {
    TextView deviceName;
    TextView deviceAddress;

[Unity3D] Timer – InvokeRepeating

유니티에서 간단하게 타이머를 구현하는 방법을 알아보겠습니다.

유니티의 Monobehavior 가 제공하는 함수들 중에

InvokeReapeating 이라는 것이 있는데

이것을 이용하면 간단하게 타이머를 만들 수 있습니다.


 private void StartTimer()
        TimeOutCount = 30;
        InvokeRepeating("CountDown", 1f, 1f);

    void CountDown()
        Debug.Log("Timer : " + TimeOutCount);
        if (TimeOutCount < 1)   


InvokeRepeating(실행할 함수명, 시간(초/float), 반복횟수(0은 무한대))


[Unity3D] NGUI – Popup 애니메이션 효과주기

NGUI 에서 제공하는 TweenScale 을 이용한 Popup 만들기

보통 NGUI를 이용해 팝업창을 만드는 때는

팝업을 만들고 GameObject 의 active 속성을 이용해 on/off 하는 방법을 사용합니다.


오늘은 여기에 간단한 애니메이션을 넣어서

이런 팝업창을 만들어 보겠습니다.



1. 우선 NGUI 를 이용해 팝업으로 사용할 오브젝트를 만듭니다.
저는 게임오버 팝업창을 만들었습니다.

2. 팝업 오브젝트에  UIScaleAnimation 이라는 스크립트를 연결해줍니다.

이 스크립트가 없다고요?

당연히 없습니다. 아직 안만들었으니까요 ㅋㅋㅋㅋ

그냥 cs 파일만 생성 해서 연결해줍시다.


3. 제가 만든  UIScaleAnimation.cs 파일은 이렇습니다.

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

public class UIScaleAnimation : MonoBehaviour {

	void Awake () {

//SetActive(true) 호출 시 실행됩니다.
    void OnEnable()
//SetActive(false) 호출 시 실행됩니다.
void OnDisable ()

 // 팝업 열기
 void open()


 float duration = 0.2f; // 애니메이션의 길이입니다.(시간)
 float startDelay = 0.2f; // 애니메이션 시작 전 딜레이입니다.
 Vector3 scaleTo = new Vector3(1f, 1f, 1f); // 오브젝트의 최종 Scale 입니다.

 // 부풀었다가 줄어드는 효과를 위한 AnimationCurve 입니다.
 AnimationCurve animationCurve = new AnimationCurve(
 new Keyframe(0f, 0f, 0f, 1f), // 0%일때 0의 값에서 시작해서 
 new Keyframe(0.7f, 1.2f, 1f, 1f), // 애니메이션 시작후 70% 지점에서 1.2의 사이즈까지 커졌다가 
 new Keyframe(1f, 1f, 1f, 0f)); // 100%로 애니메이션이 끝날때는 1.0의 사이즈가 됩니다.

 // 초기화
 void init()
 TweenScale tween = TweenScale.Begin(gameObject, duration, scaleTo);
 tween.duration = duration;
 tween.delay = startDelay;
 //tween.method = UITweener.Method.BounceIn; // AnimationCurve 대신 이것도 한번 써보세요.
 tween.animationCurve = animationCurve;


 // 팝업 닫기
 public void close()

 // 오브젝트 Disable
 void setDisable()
 gameObject.transform.localScale = new Vector3(0, 0, 0);


다른 강좌를 보니

tween.method = UITweener.Method.BounceIn

을 이용해서 팝업을 만들더군요~

그래서 써봤는데
제가 원하는 느낌이랑은 좀 맞지 않아서 AnimationCurve 를 조정해서 쓰기로 했습니다.
어떤 느낌인지는 직접 테스트해보세요~

그리고 이 스크립트를 이용하면 팝업 오브젝트에 TweenScale 컴포넌트를 따로 추가할 필요 없습니다.
그냥 이 스크립트만 쓰면 애니메이션이 실행 될 때 자동으로 추가됩니다.


void Awake ()

을 하는 이유는 처음부터 팝업 윈도우가 보이지 않게 하고
Scale을 0,0,0 으로 만들어 주기 위함입니다.

3. 이제 테스트 해봅시다.

프로젝트를 플레이 시키고 팝업 오브젝트 선택 후 Inspector 창에서
오브젝트 이름 왼쪽에있는 체크박스를 선택/해제 해봅시다.

4. 잘 된다면 닫기 버튼에

using UnityEngine;
using System.Collections;

public class UIButtonClose : MonoBehaviour {

    public UIScaleAnimation anim;

    void OnClick () 


스크립트를 달아서 버튼 클릭으로 팝업을 닫아봅시다.


잘 되시나요?


크게 어려운 것이 없으니 잘 되시겠죠? ^^:;;



NGUI 에서는 Scale 외에도 간단히 사용할 수 있는 여러가지 애니메이션을 제공합니다.

자세한 것은

를 참고하시기 바랍니다.

깊이 알아보지 않아 모르겠지만 사용방법은 대부분 비슷한 것 같네요~




고맙습니다 :)



by Ted, 20140318






Unity3D + Facebook + 재밌다~

Unity3D + Facebook +  연동 작업을 해보고 있는데


재밌다! ㅎㅎㅎ 문서를 보면서 하고 있는데

간만에 시간 가는줄 모르고 빠져들어 코딩했네…


프레임웍을 하나 짜서

앞으로 출시할 내 개인 게임들에 적용해야겠다.

(tedhome 의 게임들은 전부 Facebook 연동으로 가는거다.)(카카오따위 개나줘)


안까먹게 잘 정리해서 포스팅 해야겠다. :)


[C#] ‘System.Collections.IEnumerable’을(를) 사용할 수 없습니다.

VS에서 IEnumerable<T> 를 사용할 때

형식 인수에는 제네릭이 아닌 형식 ‘System.Collections.IEnumerable’을(를) 사용할 수 없습니다.

라는 에러가 발생할 때는

using System.Collections.Generic; 

을 추가해주면 해결 된다.

System.Collections.IEnumerable 과 System.Collections.Generic.IEnumerable 은 다른가 보다.

[Unity3D] iTween 에서 Hashtable 사용하기

iTween 을 쓸 때 저는 Hashtable 을 이용해 인자값을 넘기는 방법을 주로 사용합니다.

굉장히 단순하면서 직관적이기 때문이지요.

Hashtable 을 생성하고 -> Hash에 인자 값을 추가하고 -> iTween  함수에 넘겨주면 끝입니다.

iTween.MoveTo 함수를 예로 들어보겠습니다.

Vector3 target = new Vector3(0,0,0); // 목표점
Hashtable hash = new Hashtable();
hash.Add("position", target); // 이동 할 위치
hash.Add("speed", 3.0f); // 이동 속도 (작을수록 느림)
hash.Add("easetype", iTween.EaseType.linear); // 보간법
hash.Add("onstart", "OnItweenStart"); // iTween 이 시작 될 때 호출될 함수 지정
hash.Add("onupdate", "OnItweenUpdate"); // iTween의 동작 단계별로 호출될 함수 지정
hash.Add("oncomplete", "OnItweenEnd"); // iTween의 동작이 끝났을 때 호출될 함수 지정
iTween.MoveTo(gameObject, hash); //인자 넘겨주기


위의 코드 처럼 구현하면 됩니다.

각 인자들은 생략이 가능합니다만

애니메이션을 구현하는데 필요한 기본적인 인자들은 넣어주어야 겠지요?

(이동을 시키는데 목표점과 속도는 있어야 겠지요? ㅎㅎ;;)


iTween 은 다양한 애니메이션 함수를 지원하는데

각 함수마다 필요한 인자의 종류가 다릅니다.

이것은 iTween 공식 문서를 참고하시기 바랍니다 :)

iTween Documentation


by Ted, 201403