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

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

戦闘【UnityでRTSを作る 5】

前回の記事では陣営を実装しました。
今回は陣営が分かれたNPCに戦闘を行わせたかったので戦闘を実装します。

攻撃目標を見つける

Linqを利用して攻撃目標を見つける関数を用意しました。
最も近い敵を見つけられます。

関数を呼ぶたびにFindObjectsOfTypeは避けたかったので、
シーンのCubeKunはリストに入れます。

CubeKun.cs

public static List<CubeKun> list = new List<CubeKun>();

protected override void OnEnable () {
	base.OnEnable();
	list.Add(this);
}

protected new void OnDisable () {
	base.OnDisable();
	list.Remove(this);
}

public CubeKun GetTarget () {
	return
		list.Where(c => c != this && Team != c.Team).
		OrderBy(c => Vector3.Distance(GetFeetPosition(),c.GetFeetPosition())).
		FirstOrDefault();
}


そしてCubeKunにTargetという抽象プロパティを追加します。

CubeKun.cs

public abstract CubeKun Target { get; set; }


Playerには自動プロパティで実装しました。
Updateで攻撃目標が存在しない場合に攻撃目標を探します。
Update関数をオーバーライドしていますが、これは後述のエイミングの実装によるものです。
ちなみに、プレイヤーの移動を実装した記事から移動方法が変化しています。

Player.cs

public override CubeKun Target { get; set; }

private RaycastHit hit;

protected override void Update () {
	base.Update();

	if (!Target) Target = GetTarget();

	canMove = Input.GetMouseButton(0);
	canSearch = canMove;
	if (canMove && Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit)) {
		Pointer.position = hit.point;
		MoveToPointerPosition();
	}
}


NPCにはTargetのSetterにtarget(経路探索の移動目標)を共に更新する処理を実装しています。
プレイヤーはポインターの方へ移動しないといけませんが、
NPCは攻撃目標に向かえばいいからです。

NPC.cs

public CubeKun Target {
	get { return _Target; }
	set {
		_Target = value;
		target = value ? value.Tr : null;
	}
}
private CubeKun _Target = null;

protected override void Update () {
	base.Update();
	if (target) {
		MoveTo(target.position);
	} else {
		Target = GetTarget();
	}
}

エイミング

この記事では腕を回転させることで狙いを定めさせます。
そのため、最初に腕の参照をしなければいけません。

腕の参照

これが標準的なキューブ君の階層です。
f:id:MackySoft:20170418213951j:plain
腕の名前が「Arm_L」と「Arm_R」です。
左腕には「MachineGun」という名の武器を持たせています。

CubeKunに腕のTransformの参照を持たせる配列を用意します。

CubeKun.cs

public Transform[] Arms { get; private set; }


さらにAwake関数に腕を見つける処理を追加します。

Arms = new Transform[] {
	Tr.FindChild("Arm_L"),
	Tr.FindChild("Arm_R")
};

腕を回転させる

Targetの方向に腕を回転させるためにUpdate関数を用意します。

CubKun.cs

public float armSpeed = 10;

protected virtual new void Update () {
	if (Target) {
		for (int i = 0;Arms.Length > i;i++) {
			var dir = Target.Tr.position - Arms[i].position;
			dir.y = 0;
			var newDir = Vector3.RotateTowards(
				Arms[i].forward,
				dir,
				armSpeed * Time.deltaTime,
				0
			);
			Arms[i].rotation = Quaternion.LookRotation(newDir);
		}
	} else {
		for (int i = 0;Arms.Length > i;i++) {
			Arms[i].localRotation = Quaternion.Euler(Vector3.zero);
		}
	}
}

armSpeedが腕の回転速度を決めます。
攻撃目標が存在する場合は、狙いを定め、存在しない場合はデフォルトの値に戻します。

完成イメージ

余談ですが弾がやたらと見えづらかったのでTrailRendererを追加しました。