//tips
//spriteAtlasの使用
コルーチンで画像を切り替えるために、切り替える画像をパッケージ化できるspriteAtlasを使用する。
また、パッケージすることにより処理が軽くなるなどの利点もある。
SpriteAtlasはプロジェクトビューのCreate - Sprite Atlasからファイルを作成できる。
パックするため生成したSpriteAtlasのObjects for PackingにパックしたいSpriteを指定する。
sprite editorで大元の画像を加工したら、加工画像と別途に大元の画像を再度Unityに読み込んでおく必要がある。
パックしたい部品分のspriteが必要となる。
https://docs.unity3d.com/ja/2018.4/Manual/SpriteAtlasWorkflow.html
//imageとSprite Rendererの違い
双方とも2Dの絵を表示するが違いがある。
Sprite Rendererは、自身でアセットを描画する機能を持っており、Sprite(アセット)に設定したポリゴン情報を元に、描画する。
Imageは、CanvasRendererとCanvasとの組み合わせで描画する機能で、Sprite(アセット)に指定したTextureとUV情報を元に描画を行う。
なので、型が分かれている。
ちなみに、Textureは画像。正確には「グラフィックを示すビットマップ」とその画像の情報。
「1ピクセル目は○色。2ピクセル目は○色。……」という画像の内容と、ファイル形式などのデータを持つ。
SpriteはTextureファイルのこの部分を実際に使用すると指定する為のクラス。
基本的にTexture=Spriteだが、複数の画像をパックにしてアトラス化した場合、1つのTextureファイルから複数のSpriteを作成することになる。
//imageコンポーネントを使用した画像切り替え
spriteAtlasを利用して画像表示しようとしたがうまくできなかったので基本に立ち返り、imageでの画像表示から行う。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// UI処理のクラスを使用する宣言
using UnityEngine.UI;
public class SpriteChange : MonoBehaviour
{
// Image コンポーネントを格納する変数
private Image m_Image;
// スプライトオブジェクトを格納する配列
public Sprite[] m_Sprite;
// スプライトオブジェクトを変更するためのフラグ
bool Change;
// ゲーム開始時に実行する処理
void Start()
{
// スプライトオブジェクトを変更するためのフラグを false に設定
Change = false;
// Image コンポーネントを取得して変数 m_Image に格納
m_Image = GetComponent<Image>();
}
// ゲーム実行中に毎フレーム実行する処理
void Update()
{
// スペースキーが押された場合
if (Input.GetKeyDown(KeyCode.Space))
{
// スプライトオブジェクトの変更フラグが true の場合
if (Change)
{
// スプライトオブジェクトの変更
//(配列 m_Sprite[0] に格納したスプライトオブジェクトを変数 m_Image に格納したImage コンポーネントに割り当て)
m_Image.sprite = m_Sprite[0];
Change = false;
}
// スプライトオブジェクトの変更フラグが false の場合
else
{
// スプライトオブジェクトの変更
//(配列 m_Sprite[1] に格納したスプライトオブジェクトを変数 m_Image に格納したImage コンポーネントに割り当て)
m_Image.sprite = m_Sprite[1];
Change = true;
}
}
}
}
これにコルーチンを追加して文字同様クリックしたら変化にする。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// UI処理のクラスを使用する宣言
using UnityEngine.UI;
public class SpriteChange : MonoBehaviour
{
// Image コンポーネントを格納する変数
private Image m_Image;
// スプライトオブジェクトを格納する配列
public Sprite[] m_Sprite;
// スプライトオブジェクトを変更するためのフラグ
// ゲーム開始時に実行する処理
IEnumerator Start()
{
m_Image = GetComponent<Image>();
m_Image.sprite = m_Sprite[0];
yield return new WaitUntil(() => Input.GetMouseButtonDown(0));
yield return null;
m_Image = GetComponent<Image>();
m_Image.sprite = m_Sprite[1];
yield return new WaitUntil(() => Input.GetMouseButtonDown(0));
yield return null;
m_Image = GetComponent<Image>();
m_Image.sprite = m_Sprite[2];
}
}
さらに顔の部分のimageと体の部分のimageとを分けることで切り替え時に変化をおこすことができる。
//UI-textの文字送り設定
まずはUIからPanelを作成。一緒に作成されるcanvasをscale with screen、match modeをexpandに設定。
その際reference resolutionを覚えておき、Panelのアンカーを中央に設定した後、同じ値をwidth, heightに入れる。
Reference Resolution では、レイアウトの基準となる解像度を指定。異なる解像度の端末で動かした場合、この解像度を基準としてパーツの比率が変更される。
Screen Match Mode では、解像度の違いをどのように吸収するかを選択する。
Panelの下にサイズを合わせたimageをおき、その下にtextを配置する。textは位置を整え、アンカーを全画面表示に変更。
Textに表示させる文字をpublic string[] scenarios; の中に入れ込み、uiText.text = scenarios[currentLine];でcurrentLineの数値変化に伴い、表示されるシナリオが変わるようにする。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // uGUIの機能を使うお約束
public class TextController2 : MonoBehaviour
{
public string[] scenarios; // シナリオを格納する
public Text uiText; // uiTextへの参照を保つ
int currentLine = 0; // 現在の行番号
void Start()
{
TextUpdate();
}
void Update()
{
// 現在の行番号がラストまで行ってない状態でクリックすると、テキストを更新する
if (currentLine < scenarios.Length && Input.GetMouseButtonDown(0))
{
TextUpdate();
}
}
// テキストを更新する
void TextUpdate()
{
// 現在の行のテキストをuiTextに流し込み、現在の行番号を一つ追加する
uiText.text = scenarios[currentLine];
currentLine++;
}
}
文字を一文字ずつ順番に表示させるには、
・想定終了時間を設定
・現在時刻がその何%程度進んだか
で判定したものをString.Substringで表示処理する。
抜き出す文字列の開始文字位置と抜き出す文字列の文字数を指定できる。文字数を省略すると文の末尾までになる。
using System;
namespace Sample
{
class Sample
{
static void Main()
{
string str = “アイウエオカキ”;
Console.WriteLine(str.Substring(0, 1));
Console.WriteLine(str.Substring(1, 5));
Console.WriteLine(str.Substring(6));
Console.ReadKey();
}
}
}
とするとString.Substringにより
ア
イウエオカ
キ
が抜き出されることになる。
scenarios.Lengthで要素数をとっているので、SetNextLine()を通し、currentLineは1から始めさせる。
文字数カウントlastUpdateCharacter = -1;は、String.Substringの文字数に関係し、初期時点で何も表示させず、updateの中でdisplayCharacterCount != lastUpdateCharacter を成り立たせるために-1とする。
まず
void Start()
{
SetNextLine();
}
でSetNextLineメソッドに飛ばす。
currentText = scenarios[currentLine];でscenarios[0]を表示文章にセット。
currentLine ++;で一文目の表示が始まったことをセット。
文字の数×一文字ごとの表示時間つまり文の想定表示時間を計算
timeUntilDisplay = currentText.Length * intervalForCharacterDisplay;
想定表示時間と比べるために時刻をセット。
timeElapsed = Time.time;
次の文に移る際にdisplayCharacterCount != lastUpdateCharacterを成り立たせる必要があるので
lastUpdateCharacter = -1;
で初期化。
次にUpdate () メソッドの中に入る。
シナリオ文の数がシナリオ文の要素数の総計より少なく、かつ、クリックされた場合、
currentLine < scenarios.Length && Input.GetMouseButtonDown(0)
SetNextLine();へ移行。
もし全シナリオ表示済み、または、クリックされていなければ、
現時刻-開始時刻で経過時間を算出、それを想定終了時間でわり、何割分経過しているかを確認。それを文のそう文字数にかけることで表示可能文字数を計算。
int displayCharacterCount = (int)(Mathf.Clamp01((Time.time - timeElapsed) / timeUntilDisplay) * currentText.Length);
表示可能文字数が前回記録した表示可能文字数と異なる場合、つまり、文章が全て表示され終わっている場合を除くとき、
displayCharacterCount != lastUpdateCharacter
テキストに対して、セットされたシナリオ文章の最初から計算された文字数までを表示し、
uiText.text = currentText.Substring(0, displayCharacterCount);
表示した文字数を前回記録として記録する。
lastUpdateCharacter = displayCharacterCount;