
マイケル
どうもこんばんは!マイケルです!

エレキベア
クマ〜〜〜〜〜〜

マイケル
最近は3Dエレキベアを動かすのを目標に3Dモデル作成をがんばっていましたが、
今日はゲーム作成側の勉強ということで、こちらの本を使って進めていきます!
今日はゲーム作成側の勉強ということで、こちらの本を使って進めていきます!

Unityゲーム開発 オンライン3Dアクションゲームの作り方

エレキベア
アクションゲームクマ!!

マイケル
こちらの画面が作成するゲームの画面になります!


エレキベア
かっこいいクマ〜〜〜!!

マイケル
移動して攻撃したりとそれなりのクオリティのゲームが作れるので、
Unityの基本操作を一通り覚えて、次のステップに進みたい人には持ってこいですね!
Unityの基本操作を一通り覚えて、次のステップに進みたい人には持ってこいですね!

マイケル
ただ、いろいろと情報が古いので調べながら直さないといけない部分も多々あるので注意です。。。

エレキベア
昔の本なのクマね

マイケル
そうなんだよね!
調べたくない人はなるべく最新の参考書をみたほうがいいかもしれません…
調べたくない人はなるべく最新の参考書をみたほうがいいかもしれません…

マイケル
とりあえずこの本を前半部分、ゲームの基本操作の部分を作り終わったので、自分の中の整理もかねて紹介しようと思います!
作成の流れについて

マイケル
この本では主に、
・移動操作の設定
・ステータスの追加
・アニメーションの設定
・攻撃処理の設定
・敵のAI設定
という流れで作成していきます!
・移動操作の設定
・ステータスの追加
・アニメーションの設定
・攻撃処理の設定
・敵のAI設定
という流れで作成していきます!

マイケル
まずはスクリプトの全体図を僕の解釈でまとめてみました!


エレキベア
ごちゃごちゃしてて分からないクマ

マイケル
これから少し分割して説明するよ

マイケル
最初は少ししっかりしたゲームを作り始めようとした時、
どういう単位でプログラムを組んだらいいかわからないと思うけど
どういう単位でプログラムを組んだらいいかわからないと思うけど

マイケル
この本で作るゲームは役割ごとにスクリプトを分けて作っているので、
全体設計の参考にも役立つと思うし、いろんなゲームに流用できるところがあると思うよ!
全体設計の参考にも役立つと思うし、いろんなゲームに流用できるところがあると思うよ!

エレキベア
それはやりがいがあるクマね
移動操作について


マイケル
最初に移動させる操作を作ります!

マイケル
まずキャラクターを移動させる共通のスクリプト「CharacterMove.cs」を作って、受け取った移動位置に移動するスクリプトを書きます
・・・・・(略)・・・・・
// 水平面での移動のためYは固定
Vector3 destinationXZ = destination;
destinationXZ.y = transform.position.y;
// 目的地までの距離と方角を求める
Vector3 direction = (destinationXZ - transform.position).normalized; // ベクトル
float distance = Vector3.Distance(transform.position, destinationXZ); // 距離
// 現在の速度を退避
Vector3 currentVelocity = velocity;
// 目的地に近づいたら到着
if (arrived || distance < StoppingDistance)
arrived = true;
// 移動速度を求める
if (arrived)
velocity = Vector3.zero;
else
// 方向ベクトル * 歩行速度
velocity = direction * walkSpeed;
・・・・・(略)・・・・・
// 重力を加える
// 下方向ベクトル * 重力加速度 * フレーム間の時間
velocity += Vector3.down * GravityPower * Time.deltaTime;
// 設置していたら思い切り地面に押し付ける
Vector3 snapGround = Vector3.zero;
if (characterController.isGrounded)
snapGround = Vector3.down;
// 新しい位置 = 移動速度ベクトル * 1フレームの時間 + 地面に押し付ける力
characterController.Move(velocity * Time.deltaTime + snapGround);

マイケル
そしてクリックやドラッグ操作を判定する「InputManager.cs」、
クリックした時に移動地点を渡す「CharacterCtrl.cs」の二つを作ってあげることで
InputManage -> PlayerCtrl -> CharacterMove
の順番でクリックした位置の情報が渡っていき、移動することができます!
クリックした時に移動地点を渡す「CharacterCtrl.cs」の二つを作ってあげることで
InputManage -> PlayerCtrl -> CharacterMove
の順番でクリックした位置の情報が渡っていき、移動することができます!
・・・・・(略)・・・・・
// クリックの状態を返す
public bool Clicked()
{
if (!moved && Input.GetButtonUp(MOUSE_LEFT_CLICK))
return true;
else
return false;
}
・・・・・(略)・・・・・
・・・・・(略)・・・・・
// 歩行Update
void Walking()
{
if (inputManager.Clicked())
{
// クリックした箇所にRayを飛ばす
Ray ray = Camera.main.ScreenPointToRay(inputManager.GetCursorPosition());
// Rayを飛ばして地面と交差した位置を求める
if (Physics.Raycast(ray,
out RaycastHit hitInfo, // 衝突したオブジェクト
RayCastMaxDistance,
(1 << LayerMask.NameToLayer("Ground")) | (1 << LayerMask.NameToLayer("EnemyHit")))) // Ground, またはEnemyHitのビットフィールド
{
// 地面をクリックした時
if (hitInfo.collider.gameObject.layer == LayerMask.NameToLayer("Ground"))
{
SendMessage("SetDestination", hitInfo.point);
}
・・・・・(略)・・・・・
}
}

エレキベア
他のキャラクターにも使いまわせるよう
役割ごとに分けてるクマね
役割ごとに分けてるクマね

マイケル
そのとおりクマ
ステータスの追加について


マイケル
これは簡単で、キャラクターのHPや名前を管理する
「CharacterStatus.cs」を作ります!
「CharacterStatus.cs」を作ります!
・・・・・(略)・・・・・
// 体力
public int HP = 100;
public int MaxHP = 100;
// 攻撃力
public int Power = 10;
// 最後に攻撃した対象
public GameObject lastAttackTarget = null;
// ----- GUI, ネットワーク設定で使用 -----
// プレイヤー
public string characterName = "Player";
・・・・・(略)・・・・・

エレキベア
これもあとで他のキャラクターにも設定できるようにするクマね

マイケル
賢いねエレキベア
アニメーションの設定について


マイケル
次にアニメーションの設定です!


マイケル
アニメーションは上記画像のようなAnimationClipの設定画面から遷移条件を指定できます!

マイケル
遷移条件を設定したら、パラメータを設定する「CharaAnimation.cs」を作ります!
void Update()
{
// runアニメーション設定
Vector3 delta_position = transform.position - prePosition;
animator.SetFloat("Speed", delta_position.magnitude / Time.deltaTime);
// Attackアニメーション設定
if(attacked && !status.attacking)
{
attacked = false;
}
animator.SetBool("Attacking", (!attacked && status.attacking));
// Downアニメーション設定
if(!isDown && status.died)
{
isDown = true;
animator.SetTrigger("Down");
}
// 現在位置を設定
prePosition = transform.position;
}

マイケル
以上の設定で、特定条件を満たした時にアニメーションが変化するようになります!
合わせて、「PlayerCtrl.cs」にもステータスを追加しておきましょう!
合わせて、「PlayerCtrl.cs」にもステータスを追加しておきましょう!
・・・・・(略)・・・・・
// Update is called once per frame
void Update()
{
// ステートに応じた処理
switch (state)
{
case State.Walking:
Walking();
break;
case State.Attacking:
Attacking();
break;
}
// ステート遷移処理
if(state != nextState)
{
state = nextState;
switch (state)
{
case State.Walking:
WalkStart();
break;
case State.Attacking:
AttackStart();
break;
case State.Died:
Died();
break;
}
}
}
・・・・・(略)・・・・・
攻撃処理について


マイケル
移動、アニメーション設定までしたら次は攻撃処理の設定です!

マイケル
攻撃する武器の範囲に「AttackArea.cs」、
攻撃を受ける範囲に「HitArea.cs」を作成しましょう!
攻撃を受ける範囲に「HitArea.cs」を作成しましょう!

マイケル
そして「AttackArea.cs」を設定した武器が当たった対象の
「HitArea.cs」に攻撃情報を送り、「PlayerCtrl.cs」内でHPを減らす処理を実装します!
「HitArea.cs」に攻撃情報を送り、「PlayerCtrl.cs」内でHPを減らす処理を実装します!
・・・・・(略)・・・・・
void OnTriggerEnter(Collider other)
{
// 攻撃が当たった相手のDamageメッセージをおくる
other.SendMessage("Damage", GetAttackInfo());
// 攻撃した対象を保存
status.lastAttackTarget = other.transform.root.gameObject;
}
・・・・・(略)・・・・・
・・・・・(略)・・・・・
void Damage(AttackArea.AttackInfo attackInfo)
{
transform.root.SendMessage("Damage", attackInfo);
}
・・・・・(略)・・・・・
・・・・・(略)・・・・・
// ダメージ受けた時の処理
// (HitArea.csからSendMessageで呼び出される)
void Damage(AttackArea.AttackInfo attackInfo)
{
status.HP -= attackInfo.attackPower;
// 死亡判定
if (status.HP <= 0)
{
status.HP = 0;
ChangeState(State.Died);
}
}
・・・・・(略)・・・・・

エレキベア
これで相手のHPを減らせるようになるクマね
敵のAI設定について


マイケル
以上でプレイヤーの動きは大体設定できたので、
最後に敵の動きを設定していきます!
最後に敵の動きを設定していきます!

マイケル
敵に設定するスクリプトも基本的にプレイヤーと一緒ですが、「SearchArea.cs」を追加し、「PlayerCtrl.cs」から「EnemyCtrl.cs」に変えています

エレキベア
具体的にどう違うクマ?

マイケル
自分で動かすプレイヤーと違って敵は自身で動いてもらわないといけないので
AI設定をしているというわけです!
AI設定をしているというわけです!

エレキベア
敵が勝手に動くようにするクマね

マイケル
「SearchArea.cs」で探索範囲の中にプレイヤーがいたらターゲットに設定して、「EnemyCtrl.cs」の中でプレイヤーを追跡するステータスを追加するよ!
・・・・・(略)・・・・・
private void OnTriggerStay(Collider other)
{
// Playerタグをターゲットにする
if (other.tag == "Player")
{
enemyCtrl.SetAttackTarget(other.transform);
}
}
・・・・・(略)・・・・・
・・・・・(略)・・・・・
// 追跡中
void Chasing()
{
// 移動先をプレイヤーに設定
SendMessage("SetDestination", attackTarget.position);
// 2m以内に近づいたら攻撃
if (Vector3.Distance(attackTarget.position, transform.position) <= 2.0f)
{
ChangeState(State.Attacking);
}
}
・・・・・(略)・・・・・
まとめ

マイケル
ざっくりと話しましたが、これまでの設定で敵が自分で動いて、
攻撃したら倒せるようになります!
攻撃したら倒せるようになります!

マイケル
ここにゲームルールや敵を生成するジェネレータを追加するだけでも割と遊べますね

エレキベア
3Dキャラを動かすのは楽しいクマね

マイケル
夢が広がるね!
今回で基本操作までは作れたから、次はUIやネットワーク設定をしていくぞ!
今回で基本操作までは作れたから、次はUIやネットワーク設定をしていくぞ!

エレキベア
楽しみクマ〜〜〜〜〜〜〜

マイケル
さて、ブログも書いたし遊ぶか〜〜〜〜


エレキベア
どんだけドラゴンおんねん

マイケル
バグらせるのも楽しいね
【Unity】オンライン3Dアクションゲームの作り方をまとめる! (前編) 〜完〜
コメント