Cz_mirror Game開発備忘録

週末にUnity でゲーム開発をしています。ゲーム開発を通じて得た情報の備忘録として活用するブログになります。

【RAYSER開発】自機から一定距離まで近づく敵キャラの動き

RAYSERで自機から一定距離まで近づく敵キャラの動きを実装してみました。

敵の近づいてくる距離はエディターで制御できるようにしています。

敵から見た自機の位置と敵の位置の距離間をVector3.Distanceで取得し、その値を条件分岐で判定し、条件を満たす場合に移動をするようにしてみました。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace RAYSER.Scripts.Enemy
{
public class EnemyMoveApproach : MonoBehaviour,IMovable
{
[SerializeField] private GameObject target;
[SerializeField] private float speed;
[SerializeField] private float stopDistance;

// Start is called before the first frame update
void Start()
{
target = GameObject.Find("Player");
}

// Update is called once per frame
void Update()
{
Move();
}

public void Move()
{
var targetPosition = target.transform.position;

transform.LookAt(targetPosition);

var distance = Vector3.Distance(transform.position, targetPosition);

if ( distance > stopDistance)
{
transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (target.transform.position - transform.position), 0.3f);
transform.position += transform.forward * speed;
}
}
}

}

RAYSERをUnityroomに公開してみました。

大遅刻ですが、テーマ「密」で公開してみました。
360度から迫り来る密集する敵をレーザーで撃破するシューティングゲームです。
Iwate & Yokohama Game Jamの作品としても公開になります。

unityroom.com

 

タイトルのアニメーションや敵のバリエーションなどもう少し手を加えてみたいので、もう少し調整などしてみます。

今はエンドレスなので、一定条件でボスキャラなども出してみたいと考えています。

【RAYSER開発】LineRendererとRayでレーザーを表現してみました。

 

LineRendererによるレーザーの表現

RAYSERでは自動追尾レーザーを実現するために、LineRendererを使って表現しています。

gyazo.com

LineRendererで線を描画する際に、プレイヤーとターゲットの位置を元に描画しました。

マテリアルを適用することでレーザーの表現が可能になります。レーザーの描画はこちらの記事を参考にさせていただきました。

aki-tk.hateblo.jp

 

Rayによる当たり判定

当たり判定ではRayを用いてみました。Rayでターゲットへの位置を取得する際に以下の情報を参考にしました。

プレイヤーのposition - ターゲットのpositionとすることでターゲットへのベクトルを求めることができるので、そこからheading.magnitudeで距離を取得、ベクトルと距離を元にプレイヤーとターゲットの正規化されたベクトルを得ることができます。

docs.unity3d.com

 

Debug.DrawLineによるRayの確認

Rayを視覚的に確認する際にDebug.DrawLineを使うことで

Gizmoを設定しておくことで、Debug.DrawLineで描画されたRayを確認することができました。注意点として、ray.direction * distanceだけではあくまでベクトルのみのため、ray.originを足して、線の開始の座標を足す必要があります。

var target = ray.origin + ray.direction * distance;
Debug.DrawLine (ray.origin, target, Color.red, 5, true);

qiita.com

LineRendererのフェードアウト

コルーチンを用いて、LineRenderer.SetColorsにアルファ値を調整することでレーザーをフェードアウトしてみました。

public IEnumerator FadeOut () {
float a = 1.0f;
while (a > 0)
{
Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);

// SetColors(StartColot, EndColor)
// 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
// 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
lineRenderer.SetColors(color, color);
yield return new WaitForSeconds(0.03f);
a -= 0.1f;
}
// α値が0になったら線の描画自体をやめる
lineRenderer.enabled = false;
yield break;
}

こちらのフェードアウトについて、青木ととさんのブログ記事を参考にさせていただきました。

lycoris102.hatenablog.com

ソースコード

LineRendererとRayを用いたレーザーを表現したソースになります。

using System.Collections;
using System.Collections.Generic;
using RAYSER.Scripts;
using UnityEngine;

public class Laser : MonoBehaviour
{
public GameObject target;
public float timer = 1.0f;
public GameObject muzzleFlash;

private LineRenderer lineRenderer;
private GameObject player;

private Vector3 firstPosition;
private Vector3 targetPosition;


public void LaserShot(GameObject shotOwner)
{
player = shotOwner;

var laserTarget = GameObject.Find("Player/LaserTarget");
target = laserTarget.GetComponent<LaserTarget>().target;

positionSetting();
drewLaserLine();
raySetting();

StartCoroutine("FadeOut");
Destroy (gameObject, timer);
}

/*
* レーザーの座標設定
*/
void positionSetting()
{
// Target Setting
firstPosition = player.transform.position;
targetPosition = new Vector3(firstPosition.x, firstPosition.y, firstPosition.z);
if (!target)
{
target = GameObject.Find("Player/NoTarget");
targetPosition = target.transform.position;
}
else
{
targetPosition = target.transform.position;
}
}

/*
* レーザー描画
*/
void drewLaserLine()
{
lineRenderer = GetComponent<LineRenderer>();
lineRenderer.enabled = true;
lineRenderer.SetVertexCount(2);

// Draw Laser
lineRenderer.SetPosition(0, firstPosition);
lineRenderer.SetPosition(1, targetPosition);

// MuzzleFlash sample
GameObject _muzzleFlash = Instantiate(muzzleFlash) as GameObject;
_muzzleFlash.transform.position = firstPosition;
_muzzleFlash.transform.LookAt(target.transform);
}

/*
* Ray設定
*/
void raySetting()
{
// Ray Setting
var heading = targetPosition - firstPosition; // Rayの目標座標
var distance = heading.magnitude; // Rayの飛ばせる距離
var direction = heading / distance; // Rayのベクトル
Ray ray = new Ray(firstPosition, direction * distance);

foreach (RaycastHit hit in Physics.RaycastAll(ray))
{
var damagetarget = hit.transform.GetComponent<IDamagable>();
if (damagetarget != null)
{
float damage = 1.0f;
hit.transform.GetComponent<IDamagable>().AddDamage(damage);
}
}

// rayの方向ベクトルにhit迄の距離をかけ合わせて方向ベクトルを作り、発射地点の座標を足して初めてターゲットの座標が算出できる
var target = ray.origin + ray.direction * distance;
Debug.DrawLine (ray.origin, target, Color.red, 5, true);


}

/*
* レーザーフェードアウト処理
*/
public IEnumerator FadeOut () {
float a = 1.0f;
while (a > 0)
{
Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, a);

// SetColors(StartColot, EndColor)
// 線の先頭と末尾で同じ色を使用しているので同じ値を指定している
// 先端から徐々にフェードアウトしたい、みたいなケースは個別に指定が必要
lineRenderer.SetColors(color, color);
yield return new WaitForSeconds(0.03f);
a -= 0.1f;
}
// α値が0になったら線の描画自体をやめる
lineRenderer.enabled = false;
yield break;
}
}

UniRx+コルーチンのダメージ後の一時的無敵処理

RAYSERという開発中のゲームでUniRxとコルーチンを用いたダメージを受けた際の、一時的な無敵処理を実装してみました。


https://gyazo.com/e89d1f4ba01090c9fee341e378fbe5ab

 

こちら具体的にはダメージを受けた際に、コルーチンの実行とともに、ReactiveProperty<bool>shieldActivateでシールドのフラグを有効にして、コルーチンの終了とともに無効にする程度の簡単なものになります。

shieldActivateを他のコンポーネントでも購読することでバリアのエフェクトを有効にする処理も別で実装しています。

 

プレイヤーのシールド関連処理(ダメージ、一時的な無敵の処理など)

using System.Collections;
using System.Collections.Generic;
using Doozy.Engine.Utils.ColorModels;
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class PresenterShield : MonoBehaviour
{
[SerializeField]
private Image imageComponent;

[SerializeField]
private GameObject player;

[SerializeField]
private Sprite[] shieldImages;

void Start()
{
if (!player)
{
player = GameObject.Find("Player");
}

if (!imageComponent)
{
imageComponent = GetComponent<Image>();
}

var playerShield = player.GetComponent<PlayerShield>();
playerShield.shield.Subscribe( x => { RefreshUI(x); }).AddTo(this);
}

// シールドUI更新
void RefreshUI(int shield)
{
var index = shield;
if (index < 0)
{
index = 0;
}

imageComponent.sprite = shieldImages[index];

}
}

 

バリアのエフェクト処理

using System.Collections;
using System.Collections.Generic;
using Doozy.Engine.Utils.ColorModels;
using UnityEngine;
using UniRx;

public class PlayerShieldEffect : MonoBehaviour
{
private GameObject player;

void Start()
{
player = transform.root.gameObject;
var playershield = player.GetComponent<PlayerShield>();

playershield.shieldActivate.Subscribe(x =>
{
ShieldActivate(x);
}).AddTo(this);

gameObject.SetActive(false);
}

void ShieldActivate(bool x)
{
if (x)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}


}

Affinity Photoでヘキサゴンパターンを作ってみました

ヘキサゴンパターンを作る動画、フィルターでラインパターンを作り、ポリゴンツールでヘキサゴンパターンベースを作って、シェイプから選択範囲を作って切り抜きなどアプリの使い方も習得できてよいですね。

youtu.be

 

f:id:godhandevilleg:20200606154711p:plain

こちら動画を参考に作ったヘキサゴンパターンです。ご自由にお使いください。

 

Iwate x Yokohama.Unity ~地方をテーマに1Dayオンラインゲームジャム~に参加しました。

Iwate x Yokohama.Unity ~地方をテーマに1Dayオンラインゲームジャム~に参加させていただきました。

iwateunity.connpass.com

 

岩手と横浜がテーマだったので、隕石と横スクロールもできるという意味でこじつけで、RAYSERという自動照準レーザーで敵を一掃するゲームの開発に着手していたので、今回こちらを作ってみることにしました。

UniRxをインストールしたところで、EventSystems関連のエラーが表示されてしまい、いろいろ調べていたのですが、バージョンアップで直ったという記載があったため、今回Unity2019.3.15f1にアップグレードしました。

 

レーザーの表現はLineRendererを使い、ロックオンはコライダーを使った簡易的なものにして、未完成ですが、現時点のものをビルドしたものをアップしてみました。
(当たり判定など諸々できていません。。)

https://unityroom.com/games/rayser

yokohama.unity #0 LT1 CorgiEngine触ってみた

先日オンラインのイベントyokohama.unityでLTをさせていただきました際の資料になります。

まだ使いこなせていませんが、CorgiEngineを少し触ってみた際の感想やデモ、チュートリアルなどの情報を少しまとめています。

yokohama.unity #0 LT1 CorgiEngine触ってみた https://speakerdeck.com/czmirror/yokohama-dot-unity-number-0-lt1-corgienginehong-tutemita
#yokohamaunity