コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【Unity】【UGUI Super ScrollView】チャット画面を作る

はじめに

 
「UGUI Super ScrollView」ではチャット画面を作ることができます

作成例は上記の GitHub リポジトリの
「Assets/Example/09_Chat/Example.unity」シーンで確認できます

作成例

f:id:baba_s:20180310205806g:plain

ソースコード

キャラクターのデータ

public sealed class CharaData
{
    private readonly int    m_id                ;
    private readonly string m_iconSpriteName    ;

    public int      Id              { get { return m_id             ; } }
    public string   IconSpriteName  { get { return m_iconSpriteName ; } }

    public CharaData
    (
        int     id              ,
        string  iconSpriteName
    )
    {
        m_id                = id                ;
        m_iconSpriteName    = iconSpriteName    ;
    }
}

スクロールの項目で使用するデータ

public sealed class ListItemData
{
    private readonly CharaData  m_charaData         ;
    private readonly string     m_message           ;
    private readonly string     m_imageSpriteName   ;
    private readonly bool       m_isMessage         ;

    public CharaData    CharaData       { get { return m_charaData          ; } }
    public string       Message         { get { return m_message            ; } }
    public string       ImageSpriteName { get { return m_imageSpriteName    ; } }
    public bool         IsMessage       { get { return m_isMessage          ; } }

    public ListItemData
    (
        CharaData   charaData       ,
        string      message         ,
        string      imageSpriteName
    )
    {
        m_charaData         = charaData         ;
        m_message           = message           ;
        m_imageSpriteName   = imageSpriteName   ;
        m_isMessage         = !string.IsNullOrEmpty( message );
    }
}

スクロールの項目

using UnityEngine;
using UnityEngine.UI;

[DisallowMultipleComponent]
public sealed class ListItemUI : MonoBehaviour
{
    private static readonly CharaData m_dummyCharaData = new CharaData( -1, string.Empty );

    [SerializeField] private RectTransform      m_rootUI        = null;
    [SerializeField] private Image              m_iconUI        = null;
    [SerializeField] private Image              m_arrowUI       = null;
    [SerializeField] private Image              m_frameUI       = null;
    [SerializeField] private RectTransform      m_frameRectUI   = null;
    [SerializeField] private Text               m_textUI        = null;
    [SerializeField] private RectTransform      m_textRectUI    = null;
    [SerializeField] private ContentSizeFitter  m_textFitterUI  = null;
    [SerializeField] private Image              m_imageUI       = null;
    [SerializeField] private RectTransform      m_imageRectUI   = null;

    public void SetDisp( ListItemData data, ListItemData prevData )
    {
        var charaData = data.CharaData;
        var isMessage = data.IsMessage;
        var prevCharaData = prevData != null ? prevData.CharaData : m_dummyCharaData;
        var isSameChara = charaData.Id == prevCharaData.Id;

        m_iconUI.gameObject.SetActive( !isSameChara );
        m_iconUI.sprite = Resources.Load<Sprite>( charaData.IconSpriteName );
        m_arrowUI.gameObject.SetActive( isMessage );
        m_frameRectUI.gameObject.SetActive( isMessage );
        m_textUI.gameObject.SetActive( isMessage );
        m_textUI.text = data.Message;
        m_textFitterUI.SetLayoutVertical();
        m_imageUI.gameObject.SetActive( !isMessage );
        m_imageUI.sprite = Resources.Load<Sprite>( data.ImageSpriteName );

        var contentSize = isMessage
            ? m_textRectUI.sizeDelta
            : m_imageRectUI.sizeDelta
        ;

        var frameSize = contentSize + new Vector2( 20, 20 );
        var color = charaData.Id == 0
            ? new Color32( 255, 255, 255, 255 )
            : new Color32( 160, 231, 90, 255 );
        ;

        m_frameRectUI.sizeDelta = frameSize;
        m_frameUI.color = color;
        m_arrowUI.color = color;

        var y = Mathf.Max( frameSize.y, 75 );

        m_rootUI.SetSizeWithCurrentAnchors( RectTransform.Axis.Vertical, y );
    }
}

スクロールビュー

using SuperScrollView;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

[DisallowMultipleComponent]
public sealed class Example : MonoBehaviour
{
    private static readonly CharaData[] m_charaList =
    {
        new CharaData( 0, "icon_1" ),
        new CharaData( 1, "icon_2" ),
        new CharaData( 2, "icon_3" ),
    };

    private static readonly string[] m_textList =
    {
        "おはようございます",
        "こんにちは\nこんにちは",
        "こんばんは\nこんばんは\nこんばんは",
        "おやすみ\nおやすみ\nおやすみ\nおやすみ",
    };

    private static readonly string[] m_imageSpriteNameList =
    {
        "emo_1",
        "emo_2",
        "emo_3",
    };

    [SerializeField] private LoopListView2  m_view      = null;
    [SerializeField] private ListItemUI     m_leftItem  = null;
    [SerializeField] private ListItemUI     m_rightItem = null;

    private List<ListItemData> m_list;

    private void Start()
    {
        m_list = new List<ListItemData>();

        for ( int i = 0; i < 1000; i++ )
        {
            var charaIndex      = Random.Range( 0, m_charaList.Length );
            var textIndex       = Random.Range( 0, m_textList.Length );
            var imageIndex      = Random.Range( 0, m_imageSpriteNameList.Length );
            var charaData       = m_charaList[ charaIndex ];
            var text            = m_textList[ textIndex ];
            var imageSpriteName = m_imageSpriteNameList[ imageIndex ];
            var isMessage       = Random.Range( 0, 5 ) != 0;

            var data = new ListItemData
            (
                charaData       : charaData,
                message         : isMessage ? text : null,
                imageSpriteName : isMessage ? null : imageSpriteName
            );

            m_list.Add( data );
        }

        m_view.InitListView( m_list.Count, OnUpdate );
    }

    private LoopListViewItem2 OnUpdate( LoopListView2 view, int index )
    {
        if ( index < 0 || m_list.Count <= index ) return null;

        var data            = m_list[ index ];
        var prevData        = m_list.ElementAtOrDefault( index + 1 );
        var charaData       = data.CharaData;
        var itemOriginal    = charaData.Id == 0 ? m_rightItem : m_leftItem;
        var itemObj         = view.NewListViewItem( itemOriginal.name );
        var itemUI          = itemObj.GetComponent<ListItemUI>();

        itemUI.SetDisp( data, prevData );

        return itemObj;
    }
}

ゲームオブジェクト

スクロールの項目

f:id:baba_s:20180310210449p:plain

スクロールビュー

f:id:baba_s:20180310210503p:plain

スクロールビューを操作するクラス

f:id:baba_s:20180310210513p:plain