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

카테고리

분류 전체보기 (2801)
Unity3D (857)
Script (91)
Extensions (16)
Effect (3)
NGUI (81)
UGUI (9)
Physics (2)
Shader (37)
Math (1)
Design Pattern (2)
Xml (1)
Tips (201)
Link (23)
World (1)
AssetBundle (25)
Mecanim (2)
Plugins (80)
Trouble Shooting (70)
Encrypt (7)
LightMap (4)
Shadow (4)
Editor (12)
Crash Report (3)
Utility (9)
UnityVS (2)
Facebook SDK (2)
iTween (3)
Font (13)
Ad (14)
Photon (2)
IAP (1)
Google (8)
Android (51)
iOS (45)
URP (2)
Programming (479)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (234)
협업 (61)
3DS Max (3)
Game (12)
Utility (140)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (16)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

다루는 내용

- Sprite Slice

- Anchor

- UI Tweener

- TypeWriter Effect


말풍선은 게임의 많은 곳에서 사용된다. 튜토리얼을 진해할 때, NPC와 대화 할 때 등.. 이러한 말 풍선을 NGUI를 사용하면 쉽게 만들 수 있다. 아래와 같이 말풍선이 커지는 트위닝과 글씨가 자동으로 써지는 타이핑 효과 그리고 말풍선 배경이 문구의 크기와 위치에 맞게 변하도록 하는 앵커의 개념을 이해한다.

준비물

NGUI, 캐릭터 이미지, 말풍선 이미지, 폰트 (NGUI는 상용 플러그인이므로 예제를 첨부할 수 없음.) 















NGUI 아틀라스 만들기

먼저 위의 그림들을 NGUI를 활용하여 아틀라스를 만든다. 메뉴의 NGUI - Open - Atlas Manker 를 차례로 클릭하여 아틀라스 메이커를 실행한다. 그리고 사용할 이미지들을 선택 하면 아래 그림처럼 Add가되고 선택 완료 후 끝으로 Create 버튼을 클릭하면 아틀라스를 저장할 곳을 묻는다. 적당한 곳에 저장하면 끝난다.


나인패치(9Patch)

추가한 말풍선 스프라이트는 작은 크기인데 어떻게 글자 수에 맞워서 늘어날 수 있을까? 그리고 늘어난 이미지는 왜 꺠져보이지 않을까? 말풍선을 9개 조각으로 나누어 활용하였기 때문이다. 나인패치 개념은 스프라이트 하나를 9족가으로 나무어 각 모서리 4부분은 고정으로 사용하고 나머지 5부분은 늘어나는 데 사용된다. 말풍선 뿐아니라 게임에서 사용하는 버튼도 9패치를 사용할 수있다. 여러 상황마다 버튼의 크기가 달라질 수 있는데 그때마다 새로운 버튼을 만들어 추가하는 것은 비효율적이다. 나인 패치를 이용하면 하나의 버튼 스프라이트로 다양한 크기의 버튼을 만들어낼 수있다. 

스프라이트를 9조각으로 나누는 방법은 간단하다. 생성한 스프라이트를 선택하고 Edit 버튼을 누른다. 그럼 UI Atlas 인스펙터가 보인다. 중간에 Border 값 들을 조절하면 점선으로 나눌 부분을 지정할 수 있게된다. 9개로 나눌 부분을 지정이 끝났다면 다시 스프라이트로 돌아와 스프라이트의 Type를 Sliced로 변경한다. 그리고 아래의 Size 에서 크기를 조절하면 9개의 영역을 나눈데로 크기가 변하는 것을 확인할 수 있다.


앵커(Anchor)

텍스트가 말풍선 스프라이트 밖으로 삐져나가면 안된다. 말풍선은 말풍선안의 텍스트 포함해야한다. 이것을 해결하기 위해 2가지 방법이 있다. 먼저 말풍선의 크기를 고정하고 메세지 라벨의 크기도 그 안에서만 보이도록 하는 것이다. 하지만 고정된 말풍선 영역 안에서 텍스트의 양이 많다면 자연적으로 텍스트가 작아지는 단점이있다. 이 방법을 사용하려면 라벨의 Overflow를 shrink로 설정하고 Size를 말풍선에 맞게 수정해야 한다. shrink로 설정하였기 때문에 텍스트는 설정 영역 밖으로 나가지 않는다. 또 한가지 방법은 텍스트는 글자 수에 따라 자유롭게 늘어날 수있고 이것에 대응하여 말풍선 배경의 사이즈가 조절되는 방식이다. 첫 번째 방법은 텍스트가 많을 경우 글씨 크기가 작아지는 단점이있다. 그래서 보통 두 번째 방법을 사용한다. 크기가 자유로은 텍스트의 크기를 말풍선이 따라가기 위해서 필요한 것이 앵커이다. 말풍선은 이미 9패치로 자유롭게 크기 조절이 가능한 상태이다. 그러므로 말풍선 스프라이터의 앵커를 텍스트에 맞추면 된다. 라벨의 Overflow는 Resize freely로 설정한다. 

앵커를 설정하는 것은 어렵지 않다. 위 그림처럼 말풍선 스프라이트의 인스펙터에서 간단히 설정한다. 타입은 None, Unified, Advenced 가 있다. None는 앵커를 사용하지 않는 것이다. Unfied는 단일 타겟을 4방향에서 지정한 수치만큼 앵커를 잡는 것이다. 마지막으로 Advenced는 4방향을 각각 원하는 타겟을 잡고 수치를 지정하는 방식이다. 타겟을 서로 다르게 지정할 수도있고 지정하지 않을 수도있다. Excute 는 앵커가 동작하는 시점을 말한다. OnEnable 은 해당 오브젝트가 꺼진상태에서 활성화 될 때 호출, OnUpdate는 매 프래임마다, OnStart는 씬이 시작할 때 한 번 호출된다. 이번 예제에서는 텍스트의 크기가 시간이 따라 변화하면서 그에 맞추어 말 풍선 스프라이트의 앵커도 따라가야하기 때문에 OnUpdate로 설정하였다.


Tween Scale

NGUI의 라벨이나 스프라이트를 애니메이션할 수있게 돕는 컴포넌트이다. 크기에대한 애니메이션을 Tween Scale로 처리하고 그 밖에 Tween Position으로 위치 애니메이션, Tween Alpha로 투명도 애니메이션을 할 수 있다. 이번 예제에서 사용하는 Tween Scale은 말풍선이 캐릭터 위에서 커지는 애니메이션을 한다.

스케일 애니메이션을 할 말풍선 스프라이트에 Tween Sacle 컴포넌트를 추가한다. From 에서 시작할 크기를 지정하고 To에 끝나는 크기를 지정한다. 시작 크기를 0.5 끝 크기를 1로 설정하였다. 이렇게히면 0.5에서 1까지 말풍선의 크기가 변하게 된다. Plya Style 은 애니메이션을 반복할지 여부를 설정하는 옵션이다. 기본적으로 Once로 설정이 되어있어서 애니메이션은 한 번만 실행된다. Loop는 애니메이션을 계속 반복하는 것이고 PingPong은 From -> To ->From ->To 반복적으로 From 에서 To 그리고 To 에서 From 으로 왕복한다. Animation Curve에서는 애니메이션 이징 그래프가 등장한다. 시간에 따른 변화량을 그래프로 표현한 것이다. 클릭해면 편집창이 뜨고 초록색 선위에 오른쪽버튼을 클릭하여 Add key를 선택한다. 그리고 선을 자유자제로 조절할 수있다. Duration은 실행 시간이다. 기본적으로 1초가 세팅되어있다. Start delay는 지연시간을 의미한다. Start delay 시간 만큼 지난 후 애니메이션을 실행 시킬 수 있다. Ignore TimeScale 옵션을 체크하면 타임스케일의 영향을 받지 않고 애니메이션을 한다. 예를 들어, 게임 중 볼륨이나 진동 옵션을 변경하기 위해 설정 대화상자를 띄었을 때 게임은 일시 정지되고 설정 대화상자 안의 스프라이트나 라벨들은 시간에 따른 스케일이나 위치등의 애니메이션을 하기위해서는 해당 옵션이 체크되어있어야 한다. 마지막으로 On Finished 는 애니메이션이 종료된 후 호출할 메서드를 선택할 수 있다. 매서드가 포함된 스크립트가 붙은 오브젝트를 드래그하여 넣고 매서드를 선택하면 된다.


원하는 상황에서 Tween 실행

위 그림에서 컴포넌트의 체크가 꺼져있다. 그러므로 실행되지 않는다. 게임중에 켜는 시점을 코드로 제어하여 컴포넌트를 켤 수 있다. 그러면 원하는 상황에 애니메이션이 가능하다. 그런데 애니메이션이 끝나고 다시 켠다고해서 애니메이션이 동작하지는 않는다. 이유는 컴포넌트가 켜지는 순간 인스펙터의 옵션들의 정보를 바탕으로 애니메이션이 시작되는데 애니메이션이 끝나고 나중에 다시 켜더라도 옵션들은 이전의 정보이기 때문이다.


해결책

컴포넌트를 켜고 끄는 방식으로 애니메이션을 제어하지 말고 ResetToBeginning 과 PlayForward를 사용하여 제어한다. 위처럼 인스펙터에서 옵션들을 설정한 뒤 컴포넌트를 끈 상태로 놔두고 게임을 실행한다. 코드에서는 해당 애니메이션을 할 상황이 됐을 때, PlayForward 를 호출 해 애니메이션을 실행한다.

1
2
tweenScale.ResetToBeginning();
tweenScale.PlayForward();

다시 사작하고 싶다면 ResetToBeginning 으로 초기화 후 PlayForward로 실행할 수 있다. 오래된 NGUI 버전에서는 Play로 실행했지만 현재는 PlayForward 와 PlayReverse 로 분리되었다. 반대로도 애니메이션을 실행할 수 있는 것이다. PlayReverse 를 사용해 애니메이션을 반대로 실행했다면 이 상황에서 PlayForward를 하고싶을 떄에는 굳이 ResetToBeginning 를 할 필요 없이 바로 PlayForward해도 동작한다.


타이핑 효과

Typewriter Effect 컴포넌트를 추가하여 텍스트에 타이핑 효과를 적용할 수 있다. charsPerSecond 옵션은 초당 표시할 글자 수이다. 수치가 높을 수록 빠른 타이핑 효과가 나타난다. fadeInTime 옵션은 글자가 알파가 적용되어 나타나는 시간이다. 딱딱한 타이핑효과가 아니라 부르럽게 텍스트가 나타난다. delayOnPeriod 옵션은 . ! ? 로 문장이 끝났을 때 지연되는 시간이다. 설정된 시간이 지난 후 다은 타이핑 효과가 계속 된다. delayOnNewLine 옵션은 텍스트가 다음 행으로 넘어갈 때 지연되는 시간이다. 그리고 타이핑 효과에도 scrollView 옵셥으로 NGUI 스크롤을 적용할 수 있다. 


타이핑 효과의 역설

텍스트에 타이핑 효과를 적용하는 이유는 한 글자씩 보이게 하기 위해서인데, 그러기 위해선 텍스트를 할당해야 한다. 하지만 할당하는 순간 UI에 텍스트는 이미 모두 보여지는 상태이다. 잠깐이지만 텍스트들이 모두 보이고 없어진다 그리고 타이핑 효과가 진행된다. 이것 때문에 말풍선 전체가 잠깐 깜빡이는 것처럼 보인다. 이것을 해결하기 위해 순서를 바꿔서 실행한다. 기존에는 스케일 커지기 -> 텍스트 할당 -> 타이핑 효과의 순서로 진행 했다. 이것을 텍스트 할당 -> 타이핑 효과 -> 스케일 애니메이션의 순서로 변경하였다. 물론 이것은 편법이다. 



출처: http://teddy.tistory.com/entry/NGUI-쉽게-말풍선-만들기 [Teddy Games]

반응형
Posted by blueasa
, |

[링크] https://github.com/pumperer/InfiniteList_NGUI



Description

A component that runs on top of NGUI's UIScrollView & UITable classes for Unity3D (i.e. It requires NGUI & Unity3D) can be used with dynamic data.

Instead of instantiating a Prefab for each row in the list we are instantiating a fixed pool of objects that will be reused according to the scroll direction.

Best suited for Mobile (tested on both iOS & Android).

Features

  • Infinite scrolling with clipping panel
  • Only fixed height cells are supported for now
  • Basic Scroll indicator
  • Quick jump (selecting a start point)
  • Simple sections implementation (section height need to be equal to the item height)
  • Click item callbacks
  • Tested on Unity v4.2.2 & Unity v4.3 and NGUI v3.0.9f7

The Demo

This demo package requires both Unity3D http://unity3d.com and NGUI http://www.tasharen.com/?page_id=140 to be installed. video: https://www.youtube.com/watch?v=5xFVJqzp0kY

To run the demo:

  1. Create a new Unity Project (preferably mobile i.e. iOS or Android)
  2. Import NGUI including its examples as the demo uses the atlas's from the examples
  3. Import InfiniteListDemo folder or simply double click on InfiniteListDemoPackage
  4. Run the scene (InfiniteListDemo)

The demo package is released under the MIT License: http://opensource.org/licenses/MIT

Example of app using this component is Avatar Messenger for Android (Contacts list view) which is a free app on Google Play: https://play.google.com/store/apps/details?id=com.orange.labs.avachat

Main Classes & Methods in the Demo

InfiniteListPopulator

The main controller script that can be attached to a gameobject (e.g. the panel)

Some of the main methods included:

Initializes the list (also can be called to refresh the list with new data)

public void InitTableView(ArrayList inDataList, List<int> inSectionsIndices, int inStartIndex)

Parameters:

  • inDataList: the generic list of our data (you can change it to any type you want… just make sure to change the member variables types for dataList & OriginalData)* inNumberOfSections: number of sections (int)
  • inSectionIndices: List of integers. The start index of each section (not as fancy as indexpath in iOS but did the job for me)
  • inStartIndex: where to start

Refresh the list without changing the data (list start at startIndex value)

public void RefreshTableView()

Individual methods for changing the parameters if needed

public void SetStartIndex(int inStartIndex)
public void SetOriginalData(ArrayList inDataList)
public void SetSectionIndices(List<int> inSectionsIndices)

You can include section titles values.. or if you have more detailed sections seperators you can change the implementation of PopulateListSectionWithIndex

string GetTitleForSection(int i)
void PopulateListSectionWithIndex(Transform item, int index)

You can do your implementation of what to populate your row item with (in the demo we simply set a label to string value from our datalist array). Simply change InfiniteItemBehaviour (mentioned later below) to include more items as you want.

void PopulateListItemWithIndex(Transform item, int dataIndex)

Events that can be listened to.

public event InfiniteItemIsPressed InfiniteItemIsPressedEvent;
public event InfiniteItemIsClicked InfiniteItemIsClickedEvent;

InfiniteItemBehaviour and InfiniteSectionBehaviour

Scripts attached to the row item prefab & section prefab (Note: the item prefab need to be tagged as "listItem" and the section prefab as "listSection")

Both checks for the visiblity of the item when the list start scrolling and notifiy the InfiniteListPopulator when the items becomes invisible. you can change use them as a template and include more labels, sprites or textures.

반응형

'Unity3D > NGUI' 카테고리의 다른 글

[펌] Blur filter for UITexture in NGUI  (0) 2017.02.09
[펌] NGUI 쉽게 말풍선 만들기  (0) 2017.02.03
NGUI CoverFlow(with Reflection Shader)  (0) 2016.10.11
[Link] Unity-NGUIExtension  (0) 2016.10.10
[펌] Smart Localization with NGUI  (0) 2016.09.26
Posted by blueasa
, |

首先原帖子在这里:
http://game.ceeger.com/forum/read.php?tid=1383
 
这楼主做得非常好了,我都不知道怎么优化才好,但是本人是厌恶OnGUI主义者,所以决定要把一切OnGUI的东西根除...
 
然后附加了镜面效果,看着还行,不说那么多先来个图:
1
 
2
 
3
 
下面是NGUI的排布
5
 
4
 
主要代码,红色为修改的部分
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
 
public class NGUICoverFlow : MonoBehaviour {
    private List<GameObject> photos = new List<GameObject>();
    private int photosCount = 5;
 
    private int currentIndex = 0;
    private float MARGIN_X = 3f;  //plane 之间的间隔
    private float ITEM_W = 10f;   //plane长宽为10M(10个单位长度)
 
    private float sliderValue = 4f;
    public UISlider uiSlider;
    void Start()
    {
        loadImages();
       //uiSlider.numberOfSteps = photosCount; //这里可设成Steps模式  随个人喜好
    }
 
    void loadImages()
    {
        for (int i = 0; i < photosCount; i++)
        {
            GameObject photo = GameObject.CreatePrimitive(PrimitiveType.Plane);
            photos.Add(photo);
            photo.layer = 14; //我的相片全部作为一个单独的层  这样镜面渲染就好办了
            photo.transform.eulerAngles = new Vector3(-90f, 0f, 0f);
            photo.transform.localScale = new Vector3(1.5f, 1f, -1f);   //根据图片设定长宽比,z:-1,使图正向
            photo.renderer.material.mainTexture = Resources.Load("photo" + i.ToString(), typeof(Texture2D)) as Texture2D;
            photo.transform.parent = gameObject.transform;
        }
        moveSlider(photos.Count / 2);
    }
 
    void moveSlider(int id)
    {
        if (currentIndex == id)
            return;
        currentIndex = id;
 
        for (int i = 0; i < photosCount; i++)
        {
            float targetX = 0f;
            float targetZ = 0f;
            float targetRot = 0f;
 
            targetX = MARGIN_X * (i - id);
            //left slides
            if (i < id)
            {
                targetX -= ITEM_W * 0.6f;
                targetZ = ITEM_W * 3f / 4;
                targetRot = -60f;
 
            }
            //right slides
            else if (i > id)
            {
                targetX += ITEM_W * 0.6f;
                targetZ = ITEM_W * 3f / 4;
                targetRot = 60f;
            }
            else
            {
                targetX += 0f;
                targetZ = 0f;
                targetRot = 0f;
            }
 
            GameObject photo = photos;
            float ys = photo.transform.position.y;
            Vector3 ea = photo.transform.eulerAngles;

            iTween.MoveTo(photo, new Vector3(targetX, ys, targetZ), 1f);
            iTween.RotateTo(photo, new Vector3(ea.x, targetRot, targetZ), 1f);
        }
    }
   public void OnSliderChange(float value)

   {
       Debug.Log(value);
       moveSlider((int)(value * photosCount));
   }
}
下面是uiSlider的设置

 
镜面效果是我从某个网页找到的,请点击看:
http://blog.163.com/lnwanggang@yeah/blog/static/165332162201010611107883/
这个效果写得很好,我就不复制黏贴了,
主要是搞一个shader和一个调用的文件MirrorReflection.cs:
其实这两个东西到底什么意思我也没看懂,我会吐槽么

反正我是拿来用了
其实感觉不写shader也可以  直接拿FX/Mirror Reflection那个来用 
但是那个MirrorReflection.cs是一定要写的
几个参数默认就好了,只有m_ReflectLayers这个设置为picture的层就行了 


不过我对比过好像这个多了一句shader语句好像是image效果的意义不明
 
再自己用ps新建一个64*64的图片
rgb为106,107,106, 整个图片的透明度为40%,然后保存成png放入场景中,作为镜面的材质色

一定要
最后调整一下各个方向的位置和角度,
搞定!~ 自己动手丰衣足食   项目我就不放出来了



[출처] http://www.ceeger.com/forum/read.php?tid=1411

반응형
Posted by blueasa
, |



[Link] https://github.com/kimsama/Unity-NGUIExtension

반응형
Posted by blueasa
, |
Hey guys,

Just wanted to post a snippet in case it turns out to be helpful for anyone using an alternate localization solution with NGUI.

I'm currently using Smart Localization which can be found here: http://forum.unity3d.com/threads/173837-RELEASED-Smart-Localization-for-Unity3D

It's really good, it's free and has some neat features such as Microsoft Translate integration.

In order to use it with NGUI, simply type your string key into the label field and drag this script on.

Cheers!

Code (csharp):
  1.  
  2. using UnityEngine;
  3. using System.Collections;
  4. using System.Globalization;
  5.  
  6. [RequireComponent(typeof(UIWidget))]
  7. [AddComponentMenu("NGUI/UI/LocalizeWidget")]
  8. public class LocalizeWidget : MonoBehaviour
  9. {
  10.     // No public variables, we'll get the key from the widget field
  11.     private string key;
  12.     private string mLanguage;
  13.     private LanguageManager loc;
  14.  
  15.     // Localize the widget on start.
  16.     private void Start()
  17.     {
  18.         // Reference the language manager
  19.         loc = LanguageManager.Instance;
  20.        
  21.         // Hook up a delegate to run the localize script whenever a language was changed
  22.         loc.OnChangeLanguage += new ChangeLanguageEventHandler(Localize);
  23.        
  24.         // Initial localize run
  25.         Localize();
  26.     }
  27.    
  28.     // Incase the script didn't get the message from being inactive
  29.     private void OnEnable()
  30.     {
  31.         if(mLanguage != loc.language)
  32.             Localize();
  33.     }
  34.    
  35.     // Force-localize the widget.
  36.     private void Localize(LanguageManager thisLanguage=null)
  37.     {
  38.         UIWidget w = GetComponent<UIWidget>();
  39.         UILabel lbl = w as UILabel;
  40.         UISprite sp = w as UISprite;
  41.  
  42.         // If no localization key has been specified, use the label's text as the key
  43.         if (lbl != null)
  44.             key = lbl.text;
  45.        
  46.         string val = loc.GetTextValue(key);
  47.        
  48.         if(string.IsNullOrEmpty(val))
  49.             val = "Missing String";
  50.  
  51.         if (lbl != null)
  52.         {
  53.             // If this is a label used by input, we should localize its default value instead
  54.             UIInput input = NGUITools.FindInParents<UIInput>(lbl.gameObject);
  55.            
  56.             if (input != null  input.label == lbl)
  57.                 input.defaultText = val;
  58.             else
  59.                 lbl.text = val;
  60.         }
  61.         else if (sp != null)
  62.         {
  63.             sp.spriteName = val;
  64.             sp.MakePixelPerfect();
  65.         }
  66.        
  67.         // Set this widget's current language
  68.         mLanguage = loc.language;
  69.     }
  70. }
  71.  
 



출처 : http://forum.unity3d.com/threads/smart-localization-with-ngui.189253/


참조 : http://forum.unity3d.com/threads/released-smart-localization-for-unity3d.173837/

반응형
Posted by blueasa
, |



소스 주소 : https://github.com/totuworld/unity/



출처 : https://www.youtube.com/watch?v=G9AdSd88BFg


반응형
Posted by blueasa
, |

Momentum And Spring 


옵션을 주면.


양끝.


1~10번까지의 리스트가 있다면.


1번에서  리스트에 없는 0번위치까지 드래그가 되서 다시 1번으로 스프링되서 돌아오는 방식이다.(10번도 마찬가지 없는 11번으로 갔다가 다시 원래 10번으로 돌아옴)


Momentum 


옵션은.


그냥 정확히 끝에 1번이나 10번에서 멈춰서 양끝으로 더이상 드래그가 되질 않는 방식이다.




이 두개를 합쳐서 


Momentum And Spring 


옵션을 주고.


한쪽방향은 더이상 못움직이게.   한쪽방향은 스프링처럼 돌아오게 하려면.



UIScrollView - 클래스에서.


public bool m_BottomStop = false;
public bool m_TopStop = false;

변수 선언.

public void Drag () 의 

Vector3 constraint = mPanel.CalculateConstrainOffset(bounds.min, bounds.max);

if (constraint.magnitude > 1f)
{
    MoveAbsolute(offset * 0.5f);
mMomentum *= 0.5f;

}

이부분에.


if (constraint.magnitude > 1f)
{
MoveAbsolute(offset * 0.5f);
mMomentum *= 0.5f;

       //StopOption.
       if (m_BottomStop == true)
       {
             if (offset.y > 0)
               RestrictWithinBounds(true, canMoveHorizontally, canMoveVertically);
        }
        if (m_TopStop == true)
        {
              if (offset.y < 0)
                 RestrictWithinBounds(true, canMoveHorizontally, canMoveVertically);
         }
}

이렇게 적어주고

m_BottomStop 과 m_TopStop   에 True 값을 넣어줘서. 값을 셋팅해서 사용하면된다.


왼쪽 오른쪽도 만들고싶다면.

offset.x 를 활용하면 된다.



[출처] http://hanamoni.tistory.com/25

반응형
Posted by blueasa
, |

[원본 링크]

http://kheldon.tistory.com/2



올려진 파일은 공유해주신 위 원본링크의 소스를 개조해서 사용중입니다.(공유 감사합니다.)


[개조파일]

CUIListView.cs




[추가사항]

- SetFocusOnCenter 추가.

- WidgetBound 대신 BoxCollier를 ItemSize로 사용.

- Vertical에서 아이템이 아래로 붙는 문제 수정(위로 붙게..)


[추가사항] 2018-07-27

- ScrollBar 터치 로직 추가


반응형
Posted by blueasa
, |

프로젝트를 진행하다보면 NGUI의 label만으로는 표현이 뭔가 아쉬운 경우가 있다. 특히 게임 캐릭터나 유닛이 데미지를 받는다거나, 스코어를 보여준다거나 하는 상황에서 사이즈가 큰 폰트를 써야 할 경우가 많은데, 이럴 경우 기본 폰트의 크기가 작아 폰트가 지저분하게 보인다거나 게임 자체가 뭔가 허접(?)하게 보일 확률이 높다.

"0부터 9까지의 숫자 부분만 따로 떼어 특별한 이미지로 만든 후에 이것을 label로 쓸 수 있다면..?"

이런 생각으로, 데미지 폰트를 만드는 방법을 검색해 보았으나... BMFont를 이용한 폰트를 만드는 방법은 여기저기 블로그 등에 널려(...) 있는데 비해, 이미지로 구성된 숫자 폰트를 만드는 방법은 의외로 찾아보기 어려웠다. 약간의 삽질 끝에 숫자 폰트를 만드는 방법을 확실히 알게 되어 공유해 보겠다. 

준비물
Unity, NGUI, BMFont, 폰트로 만들 0부터 9까지의 이미지

참고로 여기서 사용한 각 툴의 버전은 다음과 같다.
Unity3D: 4.1.5
NGUI: 2.6.3
BMFont: 1.13

1. BMFont를 띄우고 0부터 9까지 폰트로 만들 숫자를 선택한다.


일반적인 BMFont를 만드는 과정과 거의 비슷한데, 폰트 중에 숫자 부분만을 선택(클릭)한다는 점이 다르다. (보통 인터넷에 돌아다니는 KS1001.txt 파일을 import하는 과정...)
숫자를 클릭하면 어두운 회색 박스가 약간 밝은 회색 박스로 변한다. 이런 식으로 0부터 9까지 선택을 한다.

2. Image Manager를 띄운다.


일반 폰트를 만들 때는 존재조차 있는지 몰랐던, Image Manager를 띄운다.

3. Import Image


Image Manager를 띄우면 달랑 메뉴 하나에 빈 창만 보이는데, 메뉴의 Image => Import image를 클릭한다.

4. Id 입력


파일을 선택하는 창이 뜨는데, 준비해둔 숫자 폰트 중 0번 이미지를 선택하자. 그러면 위와 같은 Icon Image 창이 뜬다.
여기서 주의할 점은 Id 부분인데, 0번 이미지의 Id를 48로 변경하고 Ok를 눌러주자.
나머지 1번부터 9번까지는 0번 이미지부터 순서대로 Id값을 1씩 늘려나가면 된다. 이렇게 하면 9번 이미지는 Id가 57번이 된다.


5. 설정 확인


0번부터 9번 이미지를 모두 Import했다면 위와 같은 화면을 볼 수 있을 것이다.
0부터 9까지의 문자 박스에 하늘색 점이 표시되어 있고, 밝은 회색 박스로 변해 있다는 것을 알 수 있다. 만약 자신이 작업한 결과물이 위의 스샷과 다르다면 지금까지의 작업 과정을 다시 한 번 차근차근 확인해 보자.


6. Export Options


이제 Export Options를 설정해야 한다. BMFont의 Options => Export Options를 클릭하여 옵션 창을 띄우자.
확인할 사항은 두 가지이다. 첫 번째는 Bit depth인데 32비트로 바꾸면 된다. 만약 8비트 상태 그대로 둔다면 원래의 색상이 아니라 희멀건 폰트를 보게 될 것이다. 두 번째는 Textures인데, 유니티 프로젝트에서는 대부분 png 이미지를 사용하므로, png로 바꾸면 된다.
Save bitmap font as...를 누르면 저장할 이름을 결정하는 창이 뜬다.
여기서는 DamageFont라고 정해보았다.


[참고] 이후의 과정은 일반적인 BMFont를 만드는 과정과 같다.

7. fnt를 txt로 변경


저장하면 fnt와 png 파일이 생긴다. 이 중 fnt 파일의 확장자를 fnt에서 txt로 바꾼다.


8. txt와 png를 유니티의 프로젝트로 드래그&드롭


앞의 과정에서 만든 txt와 png를 유니티의 프로젝트에 드래그&드롭한다.
이제 NGUI의 Font Maker를 열어 폰트를 만들면 되는데, 유니티 메뉴 => NGUI => Open the Font Maker를 클릭한다.


9. Font 아틀라스 만들기


지금까지의 과정을 정상적으로 진행했다면 위와 같은 모습을 볼 수 있다. 앞의 과정에서 프로젝트에 포함시켰던 txt 파일을 Font Data로 드래그하고, png 파일은 Texture로 드래그한다.
Font Name을 입력하고 Create 버튼을 누르면 프로젝트 폴더에 아틀라스와 마테리얼이 생성된다.


10. 최종 테스트


NGUI의 Widget Tool을 띄운 후, 조금 전 만든 DamageFont 아틀라스를 Font로 선택한다. Label을 만든 후 정상적으로 폰트가 출력되는지 확인하자. 지금까지의 과정을 차근차근 따라했다면 위의 스샷처럼 Scene 화면에서 데미지 폰트로 된 Label을 확인할 수 있을 것이다.


출처 : http://lianes.tistory.com/49

반응형
Posted by blueasa
, |
NGUI가 기본적으로 Sprite의 회색처리와 Bright처리를 지원하지 않아서
그동안 회색 처리된 이미지와 Bright처리된 이미지를 별도로 사용하다가,
도저히 노가다와 용량문제로 안되겠어서 구글링의 도움으로 여러 글을 참고로 만들어봤습니다.
NGUI스크립트를 일부 수정하셔야합니다. 
 
대략 다음 순서입니다.
스텝1. 새로운 쉐이더를 추가합니다.
스텝2. 만들어진 Atlas의 Material의 쉐이더를 추가한 쉐이더로 바꿉니다.
스텝3. UIAtlas의 코드를 수정합니다.
스텝4. UISprite의 코드를 수정합니다.
 
스텝1. 새로운 쉐이더 추가
NGUI/Resources/Shaders에 적당한 이름으로 저장합니다.
001Shader "Unlit/Transparent Colored (Gray)"
002{
003    Properties
004    {
005        _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
006        _EffectAmount ("Effect Amount", Range (0, 1)) = 0.0
007        _Intensity ("Intencity", float) = 1.0
008    }
009     
010    SubShader
011    {
012        LOD 100
013 
014        Tags
015        {
016            "Queue" "Transparent"
017            "IgnoreProjector" "True"
018            "RenderType" "Transparent"
019        }
020         
021        Cull Off
022        Lighting Off
023        ZWrite Off
024        Fog { Mode Off }
025        Offset -1, -1
026        Blend SrcAlpha OneMinusSrcAlpha
027 
028        Pass
029        {
030            CGPROGRAM
031                #pragma vertex vert
032                #pragma fragment frag
033                 
034                #include "UnityCG.cginc"
035     
036                struct appdata_t
037                {
038                    float4 vertex : POSITION;
039                    float2 texcoord : TEXCOORD0;
040                    fixed4 color : COLOR;
041                };
042     
043                struct v2f
044                {
045                    float4 vertex : SV_POSITION;
046                    half2 texcoord : TEXCOORD0;
047                    fixed4 color : COLOR;
048                };
049     
050                sampler2D _MainTex;
051                float4 _MainTex_ST;
052                fixed _EffectAmount;
053                half _Intensity;
054 
055                v2f vert (appdata_t v)
056                {
057                    v2f o;
058                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
059                    o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
060                    o.color = v.color;
061                    return o;
062                }
063                 
064                fixed4 frag (v2f i) : COLOR
065                {
066                    fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
067                    col.rgb = lerp(col.rgb, dot(col.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount) * _Intensity;
068                    return col;
069                }
070            ENDCG
071        }
072    }
073 
074    SubShader
075    {
076        LOD 100
077 
078        Tags
079        {
080            "Queue" "Transparent"
081            "IgnoreProjector" "True"
082            "RenderType" "Transparent"
083        }
084         
085        Pass
086        {
087            Cull Off
088            Lighting Off
089            ZWrite Off
090            Fog { Mode Off }
091            Offset -1, -1
092            ColorMask RGB
093            AlphaTest Greater .01
094            Blend SrcAlpha OneMinusSrcAlpha
095            ColorMaterial AmbientAndDiffuse
096             
097            SetTexture [_MainTex]
098            {
099                Combine Texture * Primary
100            }
101        }
102    }
103}
 
스텝2. ​원하는 Atlas의 Material의 쉐이더를 방금 추가한 쉐이더로 바꿉니다.
 
스텝3. UIAtlas.cs의 코드를 수정합니다.
01[HideInInspector][SerializeField] Material material; // 이코드를 찾아서 밑에 코드를 추가합니다.
02[HideInInspector][SerializeField] Material materialGray;  // 추가
03[HideInInspector][SerializeField] Material materialBright; // 추가
04  
05  
06    // spriteMaterial을 수정합니다.
07    public Material spriteMaterial
08    {
09        get
10        {
11            return (mReplacement != null) ? mReplacement.spriteMaterial : material;
12        }
13        set
14        {
15            if (mReplacement != null)
16            {
17                mReplacement.spriteMaterial = value;
18            }
19            else
20            {
21                materialGray = null; // 추가됨
22                materialBright = null; // 추가됨
23                if (material == null)
24                {
25                    mPMA = 0;
26                    material = value;
27                }
28                else
29                {
30                    MarkAsChanged();
31                    mPMA = -1;
32                    material = value;
33                    MarkAsChanged();
34                }
35            }
36        }
37    }
38  
39    //추가
40    public Material spriteMaterialGrayscale {
41        get {
42            if (materialGray == null) {
43                materialGray = new Material(spriteMaterial);
44                materialGray.SetFloat("_EffectAmount", 1);
45            }
46            return materialGray;
47        }
48    }
49  
50    //추가
51    public Material spriteMaterialBright {
52        get {
53            if (materialBright == null) {
54                materialBright = new Material(spriteMaterial);
55                materialBright.SetFloat("_Intensity", 3);
56            }
57            return materialBright;
58        }
59    }
 
스텝4. UISprite.cs코드를 수정합니다.
01// 적당한 위치에 추가합니다.
02 [System.NonSerialized] bool isGray  = false; // 추가
03 [System.NonSerialized] bool isBright  = false; // 추가
04 
05 
06 // material getter를 수정합니다.
07 public override Material material {
08     get {
09         if (mAtlas == null) {
10             return null;
11         }
12         if (isGray) {
13             return mAtlas.spriteMaterialGrayscale;
14         }
15         if (isBright) {
16             return mAtlas.spriteMaterialBright;
17         }
18         return mAtlas.spriteMaterial;
19     }
20 }
21 
22// 추가합니다.
23 public void GrayScale(bool gray) {
24     isGray = gray;
25     if (panel != null) {
26         panel.RebuildAllDrawCalls();
27     }
28 }
29 
30// 추가합니다.
31 public void Bright(bool bright) {
32     isBright = bright;
33     if (panel != null) {
34         panel.RebuildAllDrawCalls();
35     }
36 }
 
여기까지 하셨으면 작업완료!
아래와 같이 회색처리 / Bright처리 가능합니다.
sprite.GrayScale(true);
sprite.Bright(true);NGUI가 기본적으로 Sprite의 회색처리와 Bright처리를 지원하지 않아서
그동안 회색 처리된 이미지와 Bright처리된 이미지를 별도로 사용하다가,
도저히 노가다와 용량문제로 안되겠어서 구글링의 도움으로 여러 글을 참고로 만들어봤습니다.
NGUI스크립트를 일부 수정하셔야합니다. 
 
대략 다음 순서입니다.
스텝1. 새로운 쉐이더를 추가합니다.
스텝2. 만들어진 Atlas의 Material의 쉐이더를 추가한 쉐이더로 바꿉니다.
스텝3. UIAtlas의 코드를 수정합니다.
스텝4. UISprite의 코드를 수정합니다.
 
스텝1. 새로운 쉐이더 추가
NGUI/Resources/Shaders에 적당한 이름으로 저장합니다.
001Shader "Unlit/Transparent Colored (Gray)"
002{
003    Properties
004    {
005        _MainTex ("Base (RGB), Alpha (A)", 2D) = "black" {}
006        _EffectAmount ("Effect Amount", Range (0, 1)) = 0.0
007        _Intensity ("Intencity", float) = 1.0
008    }
009     
010    SubShader
011    {
012        LOD 100
013 
014        Tags
015        {
016            "Queue" "Transparent"
017            "IgnoreProjector" "True"
018            "RenderType" "Transparent"
019        }
020         
021        Cull Off
022        Lighting Off
023        ZWrite Off
024        Fog { Mode Off }
025        Offset -1, -1
026        Blend SrcAlpha OneMinusSrcAlpha
027 
028        Pass
029        {
030            CGPROGRAM
031                #pragma vertex vert
032                #pragma fragment frag
033                 
034                #include "UnityCG.cginc"
035     
036                struct appdata_t
037                {
038                    float4 vertex : POSITION;
039                    float2 texcoord : TEXCOORD0;
040                    fixed4 color : COLOR;
041                };
042     
043                struct v2f
044                {
045                    float4 vertex : SV_POSITION;
046                    half2 texcoord : TEXCOORD0;
047                    fixed4 color : COLOR;
048                };
049     
050                sampler2D _MainTex;
051                float4 _MainTex_ST;
052                fixed _EffectAmount;
053                half _Intensity;
054 
055                v2f vert (appdata_t v)
056                {
057                    v2f o;
058                    o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
059                    o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
060                    o.color = v.color;
061                    return o;
062                }
063                 
064                fixed4 frag (v2f i) : COLOR
065                {
066                    fixed4 col = tex2D(_MainTex, i.texcoord) * i.color;
067                    col.rgb = lerp(col.rgb, dot(col.rgb, float3(0.3, 0.59, 0.11)), _EffectAmount) * _Intensity;
068                    return col;
069                }
070            ENDCG
071        }
072    }
073 
074    SubShader
075    {
076        LOD 100
077 
078        Tags
079        {
080            "Queue" "Transparent"
081            "IgnoreProjector" "True"
082            "RenderType" "Transparent"
083        }
084         
085        Pass
086        {
087            Cull Off
088            Lighting Off
089            ZWrite Off
090            Fog { Mode Off }
091            Offset -1, -1
092            ColorMask RGB
093            AlphaTest Greater .01
094            Blend SrcAlpha OneMinusSrcAlpha
095            ColorMaterial AmbientAndDiffuse
096             
097            SetTexture [_MainTex]
098            {
099                Combine Texture * Primary
100            }
101        }
102    }
103}
 
스텝2. ​원하는 Atlas의 Material의 쉐이더를 방금 추가한 쉐이더로 바꿉니다.
 
스텝3. UIAtlas.cs의 코드를 수정합니다.
01[HideInInspector][SerializeField] Material material; // 이코드를 찾아서 밑에 코드를 추가합니다.
02[HideInInspector][SerializeField] Material materialGray;  // 추가
03[HideInInspector][SerializeField] Material materialBright; // 추가
04  
05  
06    // spriteMaterial을 수정합니다.
07    public Material spriteMaterial
08    {
09        get
10        {
11            return (mReplacement != null) ? mReplacement.spriteMaterial : material;
12        }
13        set
14        {
15            if (mReplacement != null)
16            {
17                mReplacement.spriteMaterial = value;
18            }
19            else
20            {
21                materialGray = null; // 추가됨
22                materialBright = null; // 추가됨
23                if (material == null)
24                {
25                    mPMA = 0;
26                    material = value;
27                }
28                else
29                {
30                    MarkAsChanged();
31                    mPMA = -1;
32                    material = value;
33                    MarkAsChanged();
34                }
35            }
36        }
37    }
38  
39    //추가
40    public Material spriteMaterialGrayscale {
41        get {
42            if (materialGray == null) {
43                materialGray = new Material(spriteMaterial);
44                materialGray.SetFloat("_EffectAmount", 1);
45            }
46            return materialGray;
47        }
48    }
49  
50    //추가
51    public Material spriteMaterialBright {
52        get {
53            if (materialBright == null) {
54                materialBright = new Material(spriteMaterial);
55                materialBright.SetFloat("_Intensity", 3);
56            }
57            return materialBright;
58        }
59    }
 
스텝4. UISprite.cs코드를 수정합니다.
01// 적당한 위치에 추가합니다.
02 [System.NonSerialized] bool isGray  = false; // 추가
03 [System.NonSerialized] bool isBright  = false; // 추가
04 
05 
06 // material getter를 수정합니다.
07 public override Material material {
08     get {
09         if (mAtlas == null) {
10             return null;
11         }
12         if (isGray) {
13             return mAtlas.spriteMaterialGrayscale;
14         }
15         if (isBright) {
16             return mAtlas.spriteMaterialBright;
17         }
18         return mAtlas.spriteMaterial;
19     }
20 }
21 
22// 추가합니다.
23 public void GrayScale(bool gray) {
24     isGray = gray;
25     if (panel != null) {
26         panel.RebuildAllDrawCalls();
27     }
28 }
29 
30// 추가합니다.
31 public void Bright(bool bright) {
32     isBright = bright;
33     if (panel != null) {
34         panel.RebuildAllDrawCalls();
35     }
36 }
 
여기까지 하셨으면 작업완료!
아래와 같이 회색처리 / Bright처리 가능합니다.
sprite.GrayScale(true);
sprite.Bright(true);



출처 : http://devkorea.co.kr/bbs/board.php?bo_table=m03_lecture&wr_id=3561

반응형
Posted by blueasa
, |