前回、新しく作成したアプリを紹介しました
今回はこの吹き出しについてみていきたいと思います
コンテンツ
概要
今回作成したアプリにはこのように
回答の選択肢にセリフの吹き出し風の演出を用いています
また吹き出しのシッポがキャラクターを追従するようになっているため、キャラクターが実際に考えながら、選択肢を選び走っていく様子を表現しています
次はこの実装方法を見ていきたいと思います
実装方法
この吹き出しについて図解するとこうなります
各項目については以下の通りです
既に数値として持てるものはOとAとℓ
動的に移動し逐次取りに行くものはTとなります。
そして、ここで注目する点はAとBのY座標は横移動になるため同じということです
そのため、Bの座標はX座標を求めるだけで決まることがわかりました
よってXbを求めるために皆さんご存じの1次方程式のy= ax + bを使用して
ここからxの値を求めます
xを求めるために式を変形し、x = (y – b) / aにします
なおbとaはこのようになります
a:ベクトルTOの傾き、ソースコード的にはこうなります
var to = T.position - O.position;
float a = 0.0f;
if (bo != Vector3.zero && to.x != 0)
{
a = bo.y / bo.x;
}
b:そのままOのX座標が入る
ここから計算式は
Xb=(Yb – X0)/{(Yt – Yo)/(Xt – Xo)}
となります
これでBの位置が求めることができ吹き出しのキャラクター追従が可能となりました
ソースコードはこのようになっています
using UnityEngine;
public class BaloonDotPosSetter : MonoBehaviour
{
[SerializeField] private RectTransform m_parent = null;
[SerializeField] private RectTransform m_target = null;
[SerializeField] private RectTransform m_arrowTarget = null;
[SerializeField] private float m_lerpSpeed = 2.0f;
private void Update()
{
if(m_parent == null || m_target == null || m_arrowTarget == null)
{
return;
}
var rect = transform as RectTransform;
var bo = m_arrowTarget.position - m_parent.position;
float a = 0.0f;
if (bo != Vector3.zero && bo.x != 0)
{
a = bo.y / bo.x;
}
if (a == 0.0f)
{
m_target.position = transform.position;
}
else
{
var x = (rect.position.y - m_parent.position.y) / a + m_parent.position.x;
m_target.position = Vector2.Lerp(m_target.position, new Vector2(x, rect.position.y), Time.deltaTime * m_lerpSpeed);
}
}
}
なお、Tを求めるために以下のソースコードで3D座標から2D座標に置き換え、保存することで表現しています。
using UnityEngine;
public class PlayerTracer : MonoBehaviour
{
[SerializeField] private RectTransform m_parentUI = null;
[SerializeField] private Transform m_target = null;
private void Update()
{
// オブジェクトのワールド座標→スクリーン座標変換
var targetScreenPos = Camera.main.WorldToScreenPoint(m_target.position);
// スクリーン座標変換→UIローカル座標変換
RectTransformUtility.ScreenPointToLocalPointInRectangle(
m_parentUI,
targetScreenPos,
null,
out var uiLocalPos
);
this.transform.localPosition = uiLocalPos;
}
}
まとめ
今回は数学パズルですが、アドベンチャーゲームなどでも吹き出し演出はよく使うと思います
たかが吹き出し程度ですが、演出を少しでも凝ってみたいという場合にはこのように
処理を追加してもよいかと思います
また求め方も意外とシンプルなため導入もしやすいかと思います
ただし、この前提条件はキャラクターが吹き出しの下にいる前提となりますので、
そうそうないと思いますが横や上の表示の場合はさらなるひと工夫が必要になるかと思います
O : 吹き出しの原点座標
A : 吹き出しシッポの元の座標
B:移動するシッポの座標(今回これを求めます)
T:キャラクターの2D座標
ℓ:OからA長さ