code VR

Unity×VR(109)

スポンサーリンク

//tips

//AIモンスターの挙動制御

モンスターの一度の攻撃アクションでプレイヤーに複数回の被弾が生じてしまうので、被弾回数と攻撃アクション数を合わせるよう変更する。

WaitAnimationfin()メソッドの中身にanimatorのstateの遷移状態を読み取る条件を加えることで制御できないか考える。

(!animator.IsInTransition(0) && !animator.GetCurrentAnimatorStateInfo(0).IsName("RabbitWalk3”))などのstate遷移も入れて考えていく。

EnemyState.Waitの状態にした後、animator.SetTrigger("Punch Attack”);でパンチアクションへ遷移させる際にのみコライダーを外し、アクション中は再度アクションが呼ばれないように下記のような条件にした。

animator.IsInTransition(0) && !animator.GetCurrentAnimatorStateInfo(0).IsName("PunchAttack0")

これでも複数回呼ばれてしまう。

直接ダメージを与えるGolemAttackManagerスクリプトを下記のように変更した。ゴーレムのアタックモーションに時間制限を設け、damageflagをGolemAttackManagerスクリプトで管理するようにした。MoveEnemyスクリプトからは除外。これにより、OnTriggerEnter自体が呼ばれる回数は増えたが、ダメージはしっかり接触回数と同じになっている。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GolemAttackManager : MonoBehaviour
{
public float powerEnemy = 1; //攻撃力

HPScript hPScript;

public bool damageflag=false;

[SerializeField]
GameObject ParentObject;

private void OnTriggerEnter(Collider other)
{
Debug.Log(" OnTriggerEnterGolemAttackManager");

if (other.gameObject.tag == "Player" && other.gameObject != ParentObject)
{
hPScript = other.gameObject.GetComponent<HPScript>();

if (!damageflag)
{
//hPScript.hp -= powerEnemy;
damageflag = true;
StartCoroutine("WaitDamagefin");
}

if (hPScript.hp <= 0)
{
Destroy(other.gameObject); //ゲームオブジェクトが破壊される
}
}
}

IEnumerator WaitDamagefin()
{
hPScript.hp -= powerEnemy;
yield return new WaitForSeconds(1f);
damageflag = false;
}

}

次にゴーレムにダメージを与える方を考えていく。各キャラクターのAttackManagerスクリプトのOnTriggerEnter(Collider other)メソッドにother.gameObject.tag == “Enemy”を設定する。

まずはHPUIをセットする。HPscriptを変えるか迷ったが一旦現状のスクリプトを使用。ゴーレムのtagをEnemyに変更。下記スクリプトをDeerAtackManagerスクリプトに加えた。

if (other.gameObject.tag == “Enemy”)
{
hPScript = other.gameObject.GetComponent<HPScript>();
hPScript.hp -= powerEnemy;

if (hPScript.hp <= 0)
{
Destroy(other.gameObject); //ゲームオブジェクトが破壊される
}

}

これで無事にダメージを与えることができた。

ゴーレムがdestroyされた時に下記2点のエラーが発生しているのでnullの際にはアクセスさせないように修正を加える。

"SetDestination" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:SetDestination(Vector3)
MoveEnemy:SetState(EnemyState, Transform) (at Assets/MoveEnemy.cs:217)
SearchCharacter:OnTriggerStay(Collider) (at Assets/SearchCharacter.cs:23)

"Resume" can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.AI.NavMeshAgent:set_isStopped(Boolean)
MoveEnemy:SetState(EnemyState, Transform) (at Assets/MoveEnemy.cs:218)
SearchCharacter:OnTriggerStay(Collider) (at Assets/SearchCharacter.cs:23)

SearchCharacterスクリプトには下記の修正。

if(col.transform != null)
{
moveEnemy.SetState(MoveEnemy.EnemyState.Chase, col.transform);
}

MoveEnemyスクリプトには下記の修正。

if (playerTransform.position != null)
{
navMeshAgent.SetDestination(playerTransform.position);
navMeshAgent.isStopped = false;
}

上記の修正を加えても同じエラーが出てしまう。調べたところ、ナビメッシュ上にオブジェクトが存在し、経路探索可能な状態かどうか調べるにはnullではなく、

navMeshAgent.pathStatus != NavMeshPathStatus.PathInvalid

とする必要があるとのこと。

その際にはusing UnityEngine.AI;を追加し、[SerializeField] NavMeshAgent navMeshAgent;で参照をとる必要がある。

これによりエラーが生じなくなった。

この後はゴーレム消滅後にアイテムをドロップさせる仕組みを作成する。

ゴーレムの子要素にアイテムを入れたり、ゴーレム内のスクリプトでinstantiateさせることも考えたが、ここは安全に別の空オブジェクトでゴーレムを追跡し、そのオブジェクトの子要素に非表示の形でアイテムを格納、ゴーレムdestroyの処理と同時にアイテムの表示処理を指示させて対処する。

下記のスクリプトを空オブジェクトにアタッチし、オブジェクト子要素の球を表示させてみた。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Golemfollow : MonoBehaviour
{
[SerializeField]
GameObject golem;

// Update is called once per frame
void Update()
{
Vector3 offset = new Vector3(0, 3, 0);
this.transform.position = golem.transform.position + offset;
}
}

きちんと機能している。子要素にrigidbodyを付加して自由落下も確認でき、非表示から表示に直した際にも非表示中にきちんとゴーレムを追跡し、表示のタイミングで真上から球を落とすことができた。

DeerAtackManagerスクリプトのif (other.gameObject.tag == "Enemy”)の(hPScript.hp <= 0)ダメージ計算時にGolemfollowスクリプトを呼ぶ必要がある。

OnTriggerでゴーレムにアタッチさせているスクリプトを容易にとれるので、ここは

public void Dropgolemitem()
{
dropitem.SetActive(true);
}

のようなシンプルなコードをアタッチして対応できそう。ゴーレムとアイテムはここでは一対一での対応とするので問題ない。DeerAtackManagerスクリプトも修正。

if (other.gameObject.tag == "Enemy")
{
hPScript = other.gameObject.GetComponent<HPScript>();
hPScript.hp -= powerEnemy;

golemfollowdrop = other.gameObject.GetComponent<Golemfollowdrop>();

if (hPScript.hp <= 0)
{
golemfollowdrop.Dropgolemitem();

Destroy(other.gameObject); //ゲームオブジェクトが破壊される
}

}

きちんと対応できた。dropitemをキャラクターが拾えるようにし、インベントリーUIへの反映を行わせる。

 

人気の記事

1

皆さん、ついに、エアラインでも、サブスクリプションが始まったのはご存じですか? まだ実験段階ですが、ANAが、定額全国住み放題サービスを提供する「ADDress」と組んで、国内線を4回まで定額利用可能 ...

2

無料でネットショップを開けるアプリとして多くの人に驚きを与えたBASE株式会社が、2019年10月25日東証マザーズに上場しました。2020年2月時点で90万店を超えるショップを抱えるまでに成長してい ...

3

2011年にサービスを開始してから圧倒的な成長率を誇るインテリア通販サイト 【FLYMEe/フライミー】を皆さんご存じでしょうか。 「自分のイメージするインテリア、本当に欲しいインテリアがどこにあるの ...

4

ついに、noteの月間アクティブユーザー数が4400万人(2020年3月時点)に到達しました。 そもそも、「note」とは、クリエイターが、文章やマンガ、写真、音声を投稿することができ、ユーザーはその ...

5

ボードゲームカフェが1日2回転で儲かるという記事をみつけたので興味を持ち、調べてみました。 まずは、需要がどれくらいあるのか、市場のようすからみていきましょう。 世界最大のボードゲーム市場はドイツで、 ...

-code, VR
-,

Copyright© BUSINESS HUNTER , 2023 All Rights Reserved Powered by AFFINGER5.