「Unity/3d/アニメーション/追跡」の版間の差分
提供: 初心者エンジニアの簡易メモ
(→ターゲットポイントをindex順に) |
|||
| (同じ利用者による、間の11版が非表示) | |||
| 行55: | 行55: | ||
} | } | ||
void Update() { | void Update() { | ||
| − | + | transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(playerObj.transform.position - transform.position), 0.3f); | |
| − | + | transform.position += transform.forward * speed; | |
} | } | ||
</pre> | </pre> | ||
| 行65: | 行65: | ||
==NavMeshAgent同士の接触== | ==NavMeshAgent同士の接触== | ||
NavMeshAgent同士の接触半径を狭める場合は、InspectorのNavMeshAgentのRadiusを0.5から小さくする | NavMeshAgent同士の接触半径を狭める場合は、InspectorのNavMeshAgentのRadiusを0.5から小さくする | ||
| + | |||
| + | ==逃げるロジック== | ||
| + | ターゲットをいくつか用意して、そこに向かっていくように。 | ||
| + | <pre> | ||
| + | using UnityEngine.AI; | ||
| + | public class PlayerController : MonoBehaviour | ||
| + | { | ||
| + | NavMeshAgent agent; | ||
| + | float speed = 6f; | ||
| + | GameObject enemyObj; | ||
| + | GameObject targetPointGroupObj; | ||
| + | void Start() | ||
| + | { | ||
| + | enemyObj = GameObject.Find("Enemy"); | ||
| + | targetPointGroupObj = GameObject.Find("TargetPointGroup"); | ||
| + | NavStart(); | ||
| + | } | ||
| + | // 追跡ロジック開始 | ||
| + | void NavStart() | ||
| + | { | ||
| + | if (GetComponent<NavMeshAgent>() != null) | ||
| + | { | ||
| + | agent = GetComponent<NavMeshAgent>(); | ||
| + | agent.updateRotation = false; | ||
| + | agent.updatePosition = true; | ||
| + | } | ||
| + | } | ||
| + | void Update() | ||
| + | { | ||
| + | UpdateNav(); | ||
| + | UpdateLookAt(); | ||
| + | } | ||
| + | void UpdateLookAt() | ||
| + | { | ||
| + | transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(enemyObj.transform.position - transform.position), 0.3f); | ||
| + | } | ||
| + | // 追跡ロジック | ||
| + | void UpdateNav() | ||
| + | { | ||
| + | if (agent != null) | ||
| + | { | ||
| + | if (agent.pathStatus != NavMeshPathStatus.PathInvalid) | ||
| + | { | ||
| + | // agent.SetDestination(gameObject.transform.Find("Back").transform.position); | ||
| + | agent.SetDestination(GetFarTargetPointPosition()); | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | // 敵から一番遠いターゲットポイントのPositionを返す | ||
| + | Vector3 GetFarTargetPointPosition() | ||
| + | { | ||
| + | float maxDistance = 0; | ||
| + | Vector3 maxDistancePosition = Vector3.zero; | ||
| + | foreach (Transform transform in targetPointGroupObj.GetComponentInChildren<Transform>()) | ||
| + | { | ||
| + | var distance = Vector3.Distance(enemyObj.transform.position, transform.position); | ||
| + | if (maxDistance < distance && transform.gameObject.activeSelf) | ||
| + | { | ||
| + | maxDistance = distance; | ||
| + | maxDistancePosition = transform.position; | ||
| + | } | ||
| + | } | ||
| + | return maxDistancePosition; | ||
| + | } | ||
| + | } | ||
| + | </pre> | ||
| + | 参考:https://yubeshicat.hatenablog.com/entry/2018/09/07/150259 | ||
| + | |||
| + | ===ターゲットポイントをindex順に=== | ||
| + | <pre> | ||
| + | GameObject targetPointGroupObj; | ||
| + | GameObject targetPointObj; | ||
| + | void Start() | ||
| + | { | ||
| + | targetPointGroupObj = GameObject.Find("TargetPointGroup"); | ||
| + | } | ||
| + | // ターゲットポイントをグループからindex順にPositionを返す | ||
| + | Vector3 GetNextTargetPointPosition() | ||
| + | { | ||
| + | if (targetPointObj != null) | ||
| + | { | ||
| + | var distance = Vector3.Distance(targetPointObj.transform.position, transform.position); | ||
| + | // ターゲットに近づいたらきり変える | ||
| + | if (distance < 10) | ||
| + | { | ||
| + | List<Transform> transforms = new List<Transform>(); | ||
| + | int index = 0; | ||
| + | foreach (Transform tmpTransform in targetPointGroupObj.GetComponentInChildren<Transform>()) | ||
| + | { | ||
| + | transforms.Add(tmpTransform); | ||
| + | if (tmpTransform.Equals(targetPointObj.transform)) | ||
| + | { | ||
| + | index = tmpTransform.GetSiblingIndex(); | ||
| + | } | ||
| + | } | ||
| + | if (index >= transforms.Count - 1) | ||
| + | { | ||
| + | targetPointObj = transforms[0].gameObject; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | targetPointObj = transforms[index + 1].gameObject; | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | foreach (Transform transform in targetPointGroupObj.GetComponentInChildren<Transform>()) | ||
| + | { | ||
| + | targetPointObj = transform.gameObject; // 0番目 | ||
| + | break; | ||
| + | } | ||
| + | } | ||
| + | return targetPointObj.transform.position; | ||
| + | } | ||
| + | </pre> | ||
==参考== | ==参考== | ||
2023年5月31日 (水) 02:48時点における最新版
追跡アクション追加
- 敵オブジェクトにAddComponentsでRigidbodyとCapsuleColliderを追加
- 床オブジェクトの(名前の横にある)staticにチェックをつける
- Unityメインメニュー/Window/AI/Navigationから床オブジェクトを選択し、Bakeタブを選択しBakeボタンを押す。
- 敵オブジェクトのAddComponentsからNavMeshAgentを追加
- 敵オブジェクトに以下csのようにNavMeshAgentを追加
- 障害物オブジェクトを設置してstaticにチェックを入れる。
- 障害物オブジェクトにもBakeを設定する。
using UnityEngine.AI;
public class EnemyController : MonoBehaviour
{
NavMeshAgent agent;
GameObject playerObj;
void Start()
{
playerObj = GameObject.Find("Player");
NavStart();
}
// 追跡ロジック開始
void NavStart()
{
if (GetComponent<NavMeshAgent>() != null)
{
agent = GetComponent<NavMeshAgent>();
agent.updateRotation = false;
agent.updatePosition = true;
}
}
void Update()
{
NavUpdate();
}
// 追跡ロジック
void NavUpdate()
{
if (playerObj != null && agent != null)
{
agent.SetDestination(playerObj.transform.position);
}
}
}
追跡されない時
- 対象オブジェクトのscaleを変えてみる。
- bakeを再度やってみる
正面を向いて追跡
GameObject playerObj;
float speed = 0.1f;
void Start () {
playerObj = GameObject.Find("Player");
}
void Update() {
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(playerObj.transform.position - transform.position), 0.3f);
transform.position += transform.forward * speed;
}
参考:https://qiita.com/ganbaru/items/d4fe649370ce4451db80
接触判定させる場合で、追いついて回転して、接触判定しないときはRigidbodyが足りないのかも・・
NavMeshAgent同士の接触半径を狭める場合は、InspectorのNavMeshAgentのRadiusを0.5から小さくする
逃げるロジック
ターゲットをいくつか用意して、そこに向かっていくように。
using UnityEngine.AI;
public class PlayerController : MonoBehaviour
{
NavMeshAgent agent;
float speed = 6f;
GameObject enemyObj;
GameObject targetPointGroupObj;
void Start()
{
enemyObj = GameObject.Find("Enemy");
targetPointGroupObj = GameObject.Find("TargetPointGroup");
NavStart();
}
// 追跡ロジック開始
void NavStart()
{
if (GetComponent<NavMeshAgent>() != null)
{
agent = GetComponent<NavMeshAgent>();
agent.updateRotation = false;
agent.updatePosition = true;
}
}
void Update()
{
UpdateNav();
UpdateLookAt();
}
void UpdateLookAt()
{
transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(enemyObj.transform.position - transform.position), 0.3f);
}
// 追跡ロジック
void UpdateNav()
{
if (agent != null)
{
if (agent.pathStatus != NavMeshPathStatus.PathInvalid)
{
// agent.SetDestination(gameObject.transform.Find("Back").transform.position);
agent.SetDestination(GetFarTargetPointPosition());
}
}
}
// 敵から一番遠いターゲットポイントのPositionを返す
Vector3 GetFarTargetPointPosition()
{
float maxDistance = 0;
Vector3 maxDistancePosition = Vector3.zero;
foreach (Transform transform in targetPointGroupObj.GetComponentInChildren<Transform>())
{
var distance = Vector3.Distance(enemyObj.transform.position, transform.position);
if (maxDistance < distance && transform.gameObject.activeSelf)
{
maxDistance = distance;
maxDistancePosition = transform.position;
}
}
return maxDistancePosition;
}
}
参考:https://yubeshicat.hatenablog.com/entry/2018/09/07/150259
ターゲットポイントをindex順に
GameObject targetPointGroupObj;
GameObject targetPointObj;
void Start()
{
targetPointGroupObj = GameObject.Find("TargetPointGroup");
}
// ターゲットポイントをグループからindex順にPositionを返す
Vector3 GetNextTargetPointPosition()
{
if (targetPointObj != null)
{
var distance = Vector3.Distance(targetPointObj.transform.position, transform.position);
// ターゲットに近づいたらきり変える
if (distance < 10)
{
List<Transform> transforms = new List<Transform>();
int index = 0;
foreach (Transform tmpTransform in targetPointGroupObj.GetComponentInChildren<Transform>())
{
transforms.Add(tmpTransform);
if (tmpTransform.Equals(targetPointObj.transform))
{
index = tmpTransform.GetSiblingIndex();
}
}
if (index >= transforms.Count - 1)
{
targetPointObj = transforms[0].gameObject;
}
else
{
targetPointObj = transforms[index + 1].gameObject;
}
}
}
else
{
foreach (Transform transform in targetPointGroupObj.GetComponentInChildren<Transform>())
{
targetPointObj = transform.gameObject; // 0番目
break;
}
}
return targetPointObj.transform.position;
}
