# 卵の「体力」

次、卵が強く衝突したら体力が減り、ゼロになったら卵が消える処理を追加しましょう。

## スクリプト

まず、単純な考え方で、「ぶつけたら、体力が減る」処理をにしましょう。

```c#
// 卵の体力
public class EggHP : MonoBehaviour
{
    // ぶつかるときに受けるダメージ
    [SerializeField] 
    private float hitDamage = 30;
    
    // 体力
    private float hp = 100;
    
    // 衝突の時
    private void OnCollisionEnter(Collision other)
    {
        // ぶつけたら、体力が減る
        hp -= hitDamage;

        // UIまだないため、Debug.Logで確認
        Debug.Log(hp);
      
        // 体力ゼロ以下の場合、ゲームオブジェクトを廃止
        if (hp <= 0)
            Destroy(gameObject);
    }
}
```

スクリプトを<span style="color: rgb(186, 55, 42);">**卵のプレハブ**</span>にアタッチし、転がしてみましょう。

<details id="bkmrk-%E8%AA%A4%E3%81%A3%E3%81%A6%E3%80%81%E3%83%97%E3%83%AC%E3%83%8F%E3%83%96%E3%81%A7%E3%81%AF%E3%81%AA%E3%81%8F%E3%80%81%E3%82%B7%E3%83%BC%E3%83%B3%E3%81%AE%E3%82%B2%E3%83%BC%E3%83%A0"><summary>誤って、プレハブではなく、シーンのゲームオブジェクトを編集した場合</summary>

##### 誤って、プレハブではなく、シーンのゲームオブジェクトを編集した場合

プレハブを編集すると、シーンのゲームオブジェクト（インスタンス）が変わるが、逆、ゲームオブジェクトをいじれば、プレハブが変わらない。

万が一、誤った操作でゲームオブジェクトを編集してしまった場合、２つの解決がある

**<span style="text-decoration: underline;">① ゲームオブジェクトで編集した分をプレハブに反映させる</span>**

シーンにあるゲームオブジェクトの編集分をプレハブに適用できる。もちろん、同じプレハブの元であるゲームオブジェクトも変わる。

編集した分を適用するのは「Overrides」で適用できる：

![image.png](https://class.illogic.games/uploads/images/gallery/2026-07/scaled-1680-/1Ysimage.png)

「Apply All」を押すと、変わった数値やコンポーネントをプレハブに反映される

**<span style="text-decoration: underline;">② ゲームオブジェクトをプレハブの状態に戻す</span>**

逆に、編集した分をなしにし、プレハブの状態に戻したいなら、「Revert All」を押してください

</details>### 問題１：すぐ消えてしまう！

ぶつかる時に体力が減るようにしたが、床面ともぶつかるので、転がるだけで死んでしまう！床面に新しい「Floor」タグを付けて、スクリプトで床を無視しましょう。

![image.png](https://class.illogic.games/uploads/images/gallery/2026-07/scaled-1680-/4skimage.png)

```c#
// 衝突の時
private void OnCollisionEnter(Collision other)
{
    // 床面を無視する
    if (other.gameObject.CompareTag("Floor"))
        return;
    
    // ぶつけたら、体力が減る
    hp -= hitDamage;

    // UIまだないため、Debug.Logで確認
    Debug.Log(hp);
    
    // 体力ゼロ以下の場合、ゲームオブジェクトを廃止
    if (hp <= 0)
        Destroy(gameObject);
}
```

これでまた確認してみてください。

### 問題２：優しくにしても、すぐ体力が減る

たしか、これで床で転がしても体力が減らないが、優しく壁を触れても、体力が30を減る！衝突の強さに合わせて体力が減る処理を追加しましょう。このため `Collision` の `impulse` を使用できる。`impulse` を確認するため、一旦 `OnCollisionEnter` を以下のように変えてください：

```c#
// 衝突の時
private void OnCollisionEnter(Collision other)
{
    // 床面を無視する
    if (other.gameObject.CompareTag("Floor"))
        return;
    
    // ぶつけたら、体力が減る
    hp -= hitDamage;

    // 一時的に impulse を表示
    // impulseはベクトル（強さと向き）なので、ベクトルの長さを求める
    float hitForce = other.impulse.magnitude;
    Debug.Log($"衝突の強さ：{hitForce}");
    
    // UIまだないため、Debug.Logで確認
    //Debug.Log(hp);
    
    // 体力ゼロ以下の場合、ゲームオブジェクトを廃止
    //if (hp <= 0)
    //    Destroy(gameObject);
}
```

で実行するとこのように表示される（転がり方による）

![image.png](https://class.illogic.games/uploads/images/gallery/2026-07/scaled-1680-/tRKimage.png)

これを使って、スクリプトを直しましょう。最小値と最大値の強さを Unityで設定し、

- 最小値以下なら：ゼロダメージ
- 最大値以上んら：最大ダメージ
- その間は：線形的に補間

ならば、以下のようにスクリプトを直す：

```c#
// 卵の体力
public class EggHP : MonoBehaviour
{
    // ぶつかるときに受けるダメージ
    [SerializeField] 
    private float hitDamage = 30;
    
    // 最低の衝突の強さ
    [SerializeField] 
    private float minImpulse = 4;
    
    // 最大の衝突の強さ
    [SerializeField] 
    private float maxImpulse = 20;
    
    // 体力
    private float hp = 100;
    
    // 衝突の時
    private void OnCollisionEnter(Collision other)
    {
        // 床面を無視する
        if (other.gameObject.CompareTag("Floor"))
            return;
        
        // impulseはベクトル（強さと向き）なので、ベクトルの長さを求める
        float hitForce = other.impulse.magnitude;
        
        // 最低と最大の間に正規化する
        float hitNorm = (hitForce - minImpulse) / (maxImpulse - minImpulse);
        hitNorm = Mathf.Clamp01(hitNorm); // 絶対に0と1の間にする
        
        // ぶつけたら、体力が減る
        hp -= hitDamage * hitNorm;

        // UIまだないため、Debug.Logで確認
        Debug.Log($"衝突の強さ：{hitForce}, 残りの体力：{hp}");

        // 体力ゼロ以下の場合、ゲームオブジェクトを廃止
        if (hp <= 0)
            Destroy(gameObject);
    }
}
```

これで試して、体力の減り方を見てください。