第6回では、球体だった敵の見た目を無料アセット「Robot Sphere」へ変更します。これまで作った攻撃、移動、スコアは残し、Robot本体で射撃の当たり判定を取れるようにします。
Robot SphereをMy Assetsへ追加しよう
Robot SphereのUnity Asset Storeページを開き、Add to My Assetsを押します。
Asset Storeは、Unityで使えるモデルや音などを入手できる場所です。
Package Managerからインポートしよう
UnityでWindow → Package Management → My Assetsを開き、Robot Sphereを選びます。Downloadの後にImport 1.3 to projectを押します。
Import Unity Packageでは、すべてにチェックが入った状態でImportを押します。
Assets/RobotSphereフォルダーが作られます。ピンク色のマテリアルを直そう
Robot Sphereは古いUnity向けのアセットなので、Unity 6のURPではPrefabがピンク色になることがあります。これはモデルが壊れたのではなく、Shaderが現在の描画方式に合っていない状態です。
Assets/RobotSphere/Assets/Models/Materialsを開き、次の3つのMaterialを選びます。
body_diff.mateye_matAi.matvisor_matAi.mat
それぞれのShaderをUniversal Render Pipeline/Litへ変更します。body_diff.matのBase MapへBody_diff画像を設定すると、白とオレンジの模様が戻ります。
Body_diff画像のTexture TypeはDefaultのまま使います。色や模様の画像なので、Normal mapへ変更する必要はありません。
現在の敵へRobotを取り付けよう
Assets/RobotSphere/Assets/Prefab/robotSphere.prefabを、Hierarchyにある各敵のSphereへドラッグして子にします。
Mato
└─ Sphere ← Targetタグ、EnemyAttack、MovingTarget
└─ robotSphere ← 見た目と当たり判定
子のRobotはPositionで床の位置まで下げ、Scaleで大きさを調整します。親のSphereではMesh Rendererを無効にします。親のGameObject自体は無効にしません。
RobotのAnimatorにあるApply Root Motionはオフにします。アニメーションでRobot全体が設定位置から移動することを防ぎます。
Robot本体へColliderを付けよう
子のrobotSphereへSphere Colliderを追加します。Edit Colliderを押し、Robotの胴体を囲むようにCenterとRadiusを調整します。
親SphereのSphere Colliderは無効にします。これで、画面には見えない古い球ではなく、Robot側のColliderがRaycastを受け取ります。
子に当たったら親のTargetを探そう
RobotのColliderに当たると、hit.colliderは子のrobotSphereを表します。Targetタグとゲーム用スクリプトは親Sphereにあるため、whileで親を順番に調べます。
ShootCheck.csを次のコードへ更新します。
ShootCheck.cs全体を確認する
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class ShootCheck : MonoBehaviour
{
Camera cameraComponent;
public TMP_Text scoreText;
public TMP_Text timerText;
public float timeLimit = 30f;
int score = 0;
int remainingTargets;
float timeRemaining;
bool gameEnded;
void Start()
{
cameraComponent = GetComponent<Camera>();
scoreText.text = "SCORE: " + score;
remainingTargets =
GameObject.FindGameObjectsWithTag("Target").Length;
timeRemaining = timeLimit;
timerText.text =
"TIME: " + Mathf.CeilToInt(timeRemaining);
}
void Update()
{
if (gameEnded)
{
return;
}
timeRemaining -= Time.deltaTime;
if (timeRemaining <= 0f)
{
timeRemaining = 0f;
timerText.text = "TIME: 0";
scoreText.text = "TIME UP!\nSCORE: " + score;
gameEnded = true;
return;
}
timerText.text =
"TIME: " + Mathf.CeilToInt(timeRemaining);
if (Mouse.current == null ||
!Mouse.current.leftButton.wasPressedThisFrame)
{
return;
}
Ray ray = cameraComponent.ViewportPointToRay(
new Vector3(0.5f, 0.5f, 0f));
if (!Physics.Raycast(ray, out RaycastHit hit))
{
return;
}
Debug.Log(hit.collider.gameObject.name);
Transform target = hit.collider.transform;
while (target != null &&
!target.CompareTag("Target"))
{
target = target.parent;
}
if (target == null)
{
return;
}
MovingTarget movingTarget =
target.GetComponent<MovingTarget>();
if (movingTarget != null)
{
score += movingTarget.scoreValue;
}
else
{
score++;
}
remainingTargets--;
if (remainingTargets == 0)
{
gameEnded = true;
scoreText.text = "CLEAR!\nSCORE: " + score;
}
else
{
scoreText.text = "SCORE: " + score;
}
Destroy(target.gameObject);
}
}
hit.collider.transformRaycastが当たったRobotから探索を始めます。target = target.parent1つ上の親オブジェクトへ移動します。Destroy(target.gameObject)見た目、攻撃、移動を含む敵全体を消します。古い入力スクリプトのエラーを直そう
PlayするとUnityEngine.Input.GetKeyのエラーが表示される場合があります。これは、付属のRobot Free Animが古い入力方式を使っているためです。
今回は付属スクリプトから操作しないため、RobotのRobot Free Anim (Script)をRemove Componentで削除します。AnimatorとSphere Colliderは残します。
Input設定を変更する必要はありません。自分で作ったMouseLook、PlayerMove、ShootCheckは、これまでどおり新しいInput Systemを使います。
Robotを撃って確認しよう
- Robotの胴体を撃つと、敵全体が消える。
- 撃ったときにスコアが増える。
- 倒した敵から弾が発射されなくなる。
- Consoleに赤いエラーが出ない。
Robotを撃っても反応しないとき
Robot側のSphere Colliderが有効か、親SphereのTagがTargetか、更新したShootCheckがMain Cameraに付いているかを確認しよう。
次回はRobotのアニメーションをゲームの動きに合わせ、敵らしい演出を追加します。

コメント