攻撃モーションができたので、当たり判定をやってみようと思う。
ただこれが正解というのはなくて、あとで修正したり調整したりはする。その時にソースは大幅に変えるかもしれないし、変えないかもしれない。
ようは、開発に正解はなくて、結果が自分の満足のいくものができれば正解なんですよ。
とりあえず当たり判定を付けます。
当たり判定
当たり判定は、Colliderで行います。Box Colliderを武器につけて刃の部分だけ判定をつけます。

「Is Trigger」をチェックすることで、他のColliderと接触したことがわかります。
あとこのチェックをしておくと物理法則の判定がなくなります。なので叩いた時に、相手がすっ飛んでくことを防いで、ノックバックなどを自分で設定し管理しやすいようにします。
試しに何かカカシを置こうと思います。Capsuleがちょうどいいですかね。
Hierarchy(ヒエラルキー)で右クリックを押し
3D Object -> Capsule
を選択します。
作成したCapsuleは、ちょうどいい位置に移動させます。

続いて、OnTriggerEnterイベントを最上位の親オブジェクトのスクリプトに作成、
private void OnTriggerEnter(Collider other) {
Debug.Log("OnTriggerEnter!:" + other.name);
}
試しに殴ってみます。

なるほど、子供のオブジェクトのもつColliderも親が取得することができるんだね。あと地面にも斧が当たって判定がでてますね。この記事の後半で調整します。
パーティクルを出してHitを表現
アセットストアからパーティクルを持ってきます。今回はこれ

public class PlayerController : MonoBehaviour
{
[SerializeField] private GameObject hitParticle; //ヒット字に表示するパーティクル
・・・
private void OnTriggerEnter(Collider other) {
Debug.Log("OnTriggerEnter!:" + other.name);
//当たった位置を取得する
Vector3 hitPos = other.ClosestPointOnBounds(this.transform.position);
//ここにパーティクルを生成
Instantiate(hitParticle, hitPos, Quaternion.identity);
}
}
OnTriggerEnterが来たらパーティクルを生成します。
ちょっとオブジェクトと被っているのでHitした位置より手前に持ってくる(カメラに近づける)ほうが見栄えがよくなるかもしれません。
当たり判定のタイミングを調整
このままだと地面にまで当たり判定があるので、Hit判定されてしまいます。しかも走っているだけで当たり判定がでてしまうので、何とかしなくてはいけません。
1.Tagで判定
CapsulにEnemyタグをつけます。EnemyタグはないのでAdd Tagで追加してあげます。

Enemy以外は対象外にします。
private void OnTriggerEnter(Collider other) {
//EnemyだけHitする
if (other.tag != "Enemy") return;
Debug.Log("OnTriggerEnter!:" + other.name);
//当たった位置を取得する
Vector3 hitPos = other.ClosestPointOnBounds(this.transform.position);
//ここにパーティクルを生成
Instantiate(hitParticle, hitPos, Quaternion.identity);
}
これでTerrainの判定は無視できます。
2.Attackのアニメーションの時だけ判定を有効にする
AnimatorのAttackにもタグをつけます。

Attack中のみ当たり判定が動くようにします。
using System;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
・・・
[SerializeField] private GameObject hitParticle; //ヒット字に表示するパーティクル
・・・
private Animator animator;
private int AttackTag;
// Startは、MonoBehaviourが作成された後、Updateが最初に実行される前に1回呼び出されます。
void Start()
{
animator = GetComponent<Animator>(); //Animatorコンポーネントを取得
AttackTag = Animator.StringToHash("Attack"); //AttackTagを取得
}
・・・
private void OnTriggerEnter(Collider other) {
//現在のAnimation情報を取得
AnimatorStateInfo currentBaseState = animator.GetCurrentAnimatorStateInfo(0);
if (currentBaseState.tagHash != AttackTag) return;
//EnemyだけHitする
if (other.tag != "Enemy") return;
Debug.Log("OnTriggerEnter!:" + other.name);
//当たった位置を取得する
Vector3 hitPos = other.ClosestPointOnBounds(this.transform.position);
//ここにパーティクルを生成
Instantiate(hitParticle, hitPos, Quaternion.identity);
}
}
これでAttackの時以外は、判定しないようになります。
斧を振り下ろして戻すときにも当たっていますね。ん~多分敵にあったときにノックバックさせれば武器の戻りでは当たらなくなると思います。ただ気になる場合は何か対策を考える必要があります。
- 攻撃モーションを振り下ろしと戻すに分けて振り下ろしだけAttackタグをつける
- アニメーションのイベントにて当たり判定をつける範囲を指定する

こんな感じでHitとつければスクリプトの中でOnHit(On<名称>)が呼ばれるのでそのときだけ判定させるとか
- OnHitの中でRaycastを出してそれにあたったEnemyだけ処理するとか
いろいろ試してみるしかないですね。ただ、あんまり気にしすぎると沼にはまり完成前にモチベーションが尽きるので、今はこのくらいで次に進みます。


コメント