Contents
【2DSTG制作】の動画内で表示されるコード:#11 – #20
サムネイルをクリックすると、YouTubeの動画ページに移動します。
#12:スクリプトからLive2Dモデルの色を操作
Live2Dモデルの色を操作
using Live2D.Cubism.Rendering; CubismRenderController renderController; void Start() { renderController = GetComponent<CubismRenderController>(); } private IEnumerator HitColor() { renderController.OverwriteFlagForModelScreenColors = true; yield return null; // スクリーンで白色を合成 var screenColor = new Color(0.3f, 0.3f, 0.3f, 1.0f); // 全てのパーツに指定した色を適用する for (int i = 0; i < renderController.Renderers.Length; i++) { renderController.Renderers[i].ScreenColor = screenColor; } yield return new WaitForSeconds(0.03f); // 元の色に戻す renderController.OverwriteFlagForModelScreenColors = false; }
#14:Animatorでポストプロセスを操作
Animator
Animator animator; void Start() { animator = GetComponent<Animator>(); } -------------------------------------- // 任意のタイミングで // モノクロのエフェクトを適用 animator.SetTrigger("Monochrome"); // 任意のタイミングで // モノクロのエフェクトを解除 animator.SetTrigger("Color");
#15:レーザーの実装
Laser
// オブジェクト生成から削除するまでの時間 [SerializeField] float lifeTime = 1.0f; // 弾の攻撃力 public int power = 1; // レーザーか否か public bool laser; Renderer targetRenderer; void Start() { // lifeTime秒後に削除 Destroy(gameObject, lifeTime); targetRenderer = GetComponent<Renderer>(); } void Update() { // 画面に表示されなくなったら if (!targetRenderer.isVisible) { if (laser == false) { // レーザー以外は削除 Destroy(gameObject); } else { // レーザーは攻撃力ゼロ power = 0; } } }
#16:反射レーザー
ReflectLaser
Vector2 lastVelocity = Vector2.zero; Rigidbody2D rb2d; void Start() { rb2d = GetComponent<Rigidbody2D>(); } void FixedUpdate() { // 次の速度の計算用にVelocityの値を保持しておく lastVelocity = rb2d.velocity; } void OnCollisionEnter2D(Collision2D collision) { // 反射する地形に接触したら if (collision.gameObject.tag == "Terrain") { // 接触した地形に垂直な単位ベクトル(法線ベクトル)を取得 Vector2 normalVector = collision.contacts[0].normal; // 反射ベクトルを計算 Vector2 reflectVector = Vector2.Reflect(lastVelocity, normalVector); // 速度を更新 rb2d.velocity = reflectVector; } }
#17:追尾レーザー
HomingLaser
Vector3 velocity; // 追尾レーザーの初期位置 Vector3 position; Vector3 acceleration; // ターゲットが存在しない時の目標位置 Vector3 randomPos; Transform target; // 追尾レーザーの初期位置に最も近いオブジェクト GameObject searchNearObj; // 着弾までの時間 [SerializeField] float period; void Start() { position = transform.position; searchNearObj = FindClosestEnemy(); // ターゲットが存在すれば位置を取得 if (searchNearObj != null) { target = searchNearObj.transform; } randomPos = new Vector3(4.0f, Random.Range(-1.5f, 1.5f), 0); // プレイヤーの斜め後ろにレーザーを発射 velocity = new Vector3(Random.Range(-5.0f, -2.5f), Random.Range(-6.0f, 6.0f), 0); } void Update() { acceleration = Vector3.zero; if (searchNearObj != null) { Vector3 diff = target.position - position; acceleration += (diff - velocity * period) * 2f / (period * period); } else { // ターゲットが存在しない場合は予備の目標地点に移動 Vector3 diff = randomPos - position; acceleration += (diff - velocity * period) * 2f / (period * period); } period -= Time.deltaTime; if (period < 0f) { return; } velocity += acceleration * Time.deltaTime; position += velocity * Time.deltaTime; transform.position = position; } public GameObject FindClosestEnemy() { // EnemyのTagを持つゲームオブジェクトの配列 GameObject[] gos; gos = GameObject.FindGameObjectsWithTag("Enemy"); // 最も近い位置に存在するEnemy GameObject closest = null; float distance = Mathf.Infinity; Vector3 position = transform.position; foreach (GameObject go in gos) { Vector3 diff = go.transform.position - position; float curDistance = diff.sqrMagnitude; if (curDistance < distance) { closest = go; distance = curDistance; } } // 最も近かったEnemyを返す return closest; }
#18:追尾レーザー(同時に複数発射)・ヒットエフェクト
画面内の敵ユニットをランダムに取得
public GameObject[] FindEnemy() { // EnemyのTagを持つゲームオブジェクトの配列 GameObject[] gos; gos = GameObject.FindGameObjectsWithTag("Enemy"); // 画面内の敵ユニットを格納する配列 enemyList = new GameObject[6]; int i = 0; foreach (GameObject go in gos) { // 画面外の敵ユニットは除外 if (go.transform.position.x >= 4 || go.transform.position.x <= -4) { continue; } enemyList[i] = go; i++; if (i >= 6) { i = 0; } } return enemyList; }
ヒットエフェクト
[SerializeField] GameObject hitEffect; // ヒットエフェクトの生成 public void HitEffect() { Instantiate(hitEffect, transform.position, transform.rotation); } void OnTriggerEnter2D(Collider2D collision) { // 敵ユニットに当たったら if (collision.gameObject.tag == "Enemy") { // SEを再生 SoundManager.instance.PlaySE(); // ヒットエフェクトを生成 HitEffect(); } }
#19:自機狙いの追尾レーザー
HomingLaser_Enemy
// 加速度の上限 [SerializeField] float limit; void Update() { var acceleration = Vector3.zero; var diff = target.position - position; acceleration += (diff - velocity * period) * 2f / (period * period); // 加速度の上限値を設定する if (acceleration.magnitude > limit) { acceleration = acceleration.normalized * limit; } period -= Time.deltaTime; velocity += acceleration * Time.deltaTime; position += velocity * Time.deltaTime; transform.position = position; }
#20:ヒットストップの実装
画面の停止+カメラの揺れ
using DG.Tweening; void Start() { // 初期位置を取得 initialPos = transform.position; } public void SampleB() { // 画面の停止 Time.timeScale = 0; // 対象を揺らす transform.DOShakePosition(0.4f, 0.3f, 30, 90) // timeScaleに影響されなくなる .SetUpdate(true) .OnComplete(() => { // アニメーションが終了したら時間を元に戻す Time.timeScale = 1; // カメラの位置も戻す transform.position = initialPos; }); } public void SampleC() { Time.timeScale = 0; // 画面を強めに揺らす transform.DOShakePosition(1.0f, 0.8f, 30, 1) .SetUpdate(true) .OnComplete(() => { transform.position = initialPos; // 画面をスローにする関数 SlowMotion(); }); } void SlowMotion() { Time.timeScale = 0.2f; // 3秒後にゲームオーバーの処理を実行 DOVirtual.DelayedCall(3.0f, () => GameOver()) .OnComplete(() => { Time.timeScale = 1.0f; }); }