ヒキニートがゲームを作るブログ

Unityでゲームを作る過程を投稿します

拠点の実装【UnityでRTSを作る 7】

今回は弾薬補給拠点の実装をします。

モデル

弾薬補給型拠点のモデルを作りました。
f:id:MackySoft:20170422235041j:plain

陣営の追加

陣営というよりは「無所属」を追加しました。

public enum Team {
	Independent,//Add
	Ally,
	Enemy
}


レイヤーも追加しました。
f:id:MackySoft:20170424192402j:plain

拠点の実装

拠点の基底クラスを用意します。

BasePoint.cs

[RequireComponent(typeof(Health))]
[RequireComponent(typeof(BoxCollider))]
[RequireComponent(typeof(Rigidbody))]
public abstract class BasePoint : MonoBehaviour {

}

陣営

TeamプロパティのSetterではレイヤーと色の変更を行います。

BasePoint.cs

public Team Team {
	get { return _Team; }
	set {
		_Team = value;
		gameObject.SetLayer(value.ToString());
		switch (value) {
			case Team.Independent: SetColor(Color.white); break;
			case Team.Ally: SetColor(allyColor); break;
			case Team.Enemy: SetColor(enemyColor); break;
		}
	}
}
[SerializeField]
private Team _Team = Team.Ally;

public Color allyColor = Color.blue;
public Color enemyColor = Color.red;

protected virtual void OnValidate () {
	Team = _Team;
}


レイヤーの変更をするためのSetLayer拡張メソッドはこちらの記事で紹介しています。
mackysoft.hatenablog.com

色の変更

SetColor関数で実際に色の変更を行います。

BasePoint.cs

public Renderer[] Renderers {
	get { return _Renderers != null ? _Renderers : (_Renderers = GetComponentsInChildren<Renderer>()); }
}
private Renderer[] _Renderers;

public void SetColor (Color color) {
	for (int i = 0;Renderers.Length > i;i++) {
#if UNITY_EDITOR
		if (!Application.isPlaying)
			Renderers[i].sharedMaterial.color = color;
		else
#endif
			Renderers[i].material.color = color;
	}
}

色の変更はOnValidate関数により編集中も行われるので、
RendererはAwake関数ではなくGetterで初期化し、
SetColor関数は編集中と実行中の両方に対応するために少し分岐があります。

衝突時の処理

拠点のダメージや拠点の制圧処理などの処理を実装します。

BasePoint.cs

public BoxCollider Box { get; private set; }
public Health Health { get; private set; }
public Rigidbody Rigid { get; private set; }

protected virtual void Awake () {
	Box = GetComponent<BoxCollider>();
	Box.isTrigger = true;

	Rigid = GetComponent<Rigidbody>();
	Rigid.isKinematic = true;

	Health = GetComponent<Health>();
}

protected virtual void OnTriggerEnter (Collider other) {
	var bullet = other.GetComponent<Bullet>();
	if (bullet) {
		if (Team != Team.Independent)
			Health.Value -= bullet.power;
		return;
	}
	var cubekun = other.GetComponentInParent<CubeKun>();
	if (cubekun) {
		if (Team == Team.Independent || Team != Team.Independent && Health.IsDead)
			Team = cubekun.Team;
		OnCubeKunEnter(cubekun);
	}
}

protected virtual void OnCubeKunEnter (CubeKun cubekun) { }

主な処理はOnTriggerEnter関数に実装します。

弾に当たったとき、陣営が無所属でなかったらダメージを受けます。
レイヤーの設定で敵の弾が当たらないようになっているので、
敵味方の区別は必要ありません。

キューブ君に当たったとき、「陣営が無所属」または「無所属でなくて体力が0」の時にキューブ君と同じ陣営になります。(拠点の制圧と奪取)
その後、当たったキューブ君を引数にしてOnCubeKunEnterコールバックを呼びます。

弾薬補給型拠点の実装

まず、Weaponクラスに弾薬を回復する関数を実装しました。
現在は弾薬を初期化するだけです。

Weapon.cs

public void Replenishment () {
	Magazine = I_Magazine;
	Ammo = I_Ammo;
}


CubeKunクラスに持っている武器にアクセスするためのプロパティを用意します。

CubeKun.cs

public Weapon[] Weapons { get; private set; }

protected override void Awake () {
	Weapons = GetComponentsInChildren<Weapon>();
}


材料が揃ったので弾薬補給型拠点を実装します。

AmmunitionStore.cs

public class AmmunitionStore : BasePoint {

	protected override void OnCubeKunEnter (CubeKun cubekun) {
		if (Team != cubekun.Team) return;
		for (int i = 0;cubekun.Weapons.Length > i;i++)
			cubekun.Weapons[i].Replenishment();
	}

}

OnCUbeKunEnterコールバックが呼ばれると、
衝突したのが同じ陣営のキューブ君ならそのキューブ君の武器の弾薬を補給します。

完成イメージ