3Dモデルを使用している場合の、被ダメージ時の点滅表現の実装方法。
Rendererの表示/非表示をn秒毎に切り替える事で再現した。
何回もブラッシュアップした記事。
以下、格ゲー風サンプル動画。
変更履歴
*微修正は除く。
21/03/03 コード修正
ミスもあり、酷いコードだったので、修正しました。
不確かな記事を載せて申し訳ないです。
以下変更点。
- 命名をFlashing→Flickerに変更(URLはそのまま)。
- OnCollisionEnterの位置がおかしかったのを修正。
- SetEnabledRenderersをforeach→forへ。
- enabledの反転処理を一行に。
21/08/03 記事、コード修正
- 無駄に迷わせるかも知れないので、記事の項目を統合。
- リセットを追加(キャラクターをオブジェクトプール化した場合のゲームオーバー時用)。
- 一部命名を変更。
「キャラクターの3DモデルのRenderer」が複数に分散されている場合
- コード内で細かい解説をしている。
- 実行例の雰囲気はコード内にコメントアウトして記述。
使い方
- StartやAwake等、初期化のタイミングで3DモデルのRendererを全て取得。
配列として保持しておく。 - ダメージを受けた時に、Damagedを呼ぶ。
コード
Renderer[] childrenRenderer;
bool isEnabledRenderers;
bool isDamaged;
Coroutine flicker;
float flickerDuration = 1.5f;
float flickerTotalElapsedTime;
float flickerElapsedTime;
float flickerInterval = 0.075f;
void Awake()
{
childrenRenderer = GetComponentsInChildren<Renderer>();
}
void Damaged()
{
if (isDamaged)
return;
StartFlicker();
}
void SetEnabledRenderers(bool b)
{
for (int i = 0; i < childrenRenderer.Length; i++)
{
childrenRenderer[i].enabled = b;
}
}
void StartFlicker()
{
flicker = StartCoroutine(Flicker());
}
IEnumerator Flicker()
{
isDamaged = true;
flickerTotalElapsedTime = 0;
flickerElapsedTime = 0;
while (true) {
flickerTotalElapsedTime += Time.deltaTime;
flickerElapsedTime += Time.deltaTime;
if (flickerInterval <= flickerElapsedTime) {
flickerElapsedTime = 0;
isEnabledRenderers = !isEnabledRenderers;
SetEnabledRenderers(isEnabledRenderers);
}
if (flickerDuration <= flickerTotalElapsedTime) {
isDamaged = false;
isEnabledRenderers = true;
SetEnabledRenderers(true);
flicker = null;
yield break;
}
yield return null;
}
}
void ResetFlicker()
{
if (flicker != null) {
StopCoroutine(flicker);
flicker = null;
}
}
「キャラクターの3DモデルのRenderer」が一つの場合
- コード内で細かい解説をしている。
- 実行例の雰囲気はコード内にコメントアウトして記述。
使い方
- 3DモデルのRendererをインスペクターから紐付け or 初期化時にGetComponentChildrenで取得。
- ダメージを受けた時に、Damagedを呼ぶ。
コード
[SerializeField]
Renderer renderer;
bool isDamaged;
Coroutine flicker;
float flickerDuration = 1.5f;
float flickerTotalElapsedTime;
float flickerElapsedTime;
float flickerInterval = 0.075f;
void Awake()
{
}
void Damaged()
{
if (isDamaged)
return;
StartFlicker();
}
void StartFlicker()
{
flicker = StartCoroutine(Flicker());
}
IEnumerator Flicker()
{
isDamaged = true;
flickerTotalElapsedTime = 0;
flickerElapsedTime = 0;
while (true) {
flickerTotalElapsedTime += Time.deltaTime;
flickerElapsedTime += Time.deltaTime;
if (flickerInterval <= flickerElapsedTime) {
flickerElapsedTime = 0;
renderer.enabled = !renderer.enabled;
}
if (flickerDuration <= flickerTotalElapsedTime) {
isDamaged = false;
renderer.enabled = true;
flicker = null;
yield break;
}
yield return null;
}
}
void ResetFlicker()
{
if (flicker != null) {
StopCoroutine(flicker);
flicker = null;
}
}