facebook twitter hatena line email

「Unity/3d/アニメーション/追跡」の版間の差分

提供: 初心者エンジニアの簡易メモ
移動: 案内検索
(追跡されない時)
(ターゲットポイントをindex順に)
 
(同じ利用者による、間の19版が非表示)
行2: 行2:
 
#敵オブジェクトにAddComponentsでRigidbodyとCapsuleColliderを追加
 
#敵オブジェクトにAddComponentsでRigidbodyとCapsuleColliderを追加
 
#床オブジェクトの(名前の横にある)staticにチェックをつける
 
#床オブジェクトの(名前の横にある)staticにチェックをつける
#Window/AI/Navigationから床オブジェクトを選択し、Bakeタブを選択しBakeボタンを押す。
+
#Unityメインメニュー/Window/AI/Navigationから床オブジェクトを選択し、Bakeタブを選択しBakeボタンを押す。
 
#敵オブジェクトのAddComponentsからNavMeshAgentを追加
 
#敵オブジェクトのAddComponentsからNavMeshAgentを追加
 
#敵オブジェクトに以下csのようにNavMeshAgentを追加
 
#敵オブジェクトに以下csのようにNavMeshAgentを追加
#障害物オブジェクトを設置してstaicにチェックを入れる。
+
#障害物オブジェクトを設置してstaticにチェックを入れる。
 
#障害物オブジェクトにもBakeを設定する。
 
#障害物オブジェクトにもBakeを設定する。
 
<pre>
 
<pre>
行11: 行11:
 
public class EnemyController : MonoBehaviour
 
public class EnemyController : MonoBehaviour
 
{
 
{
    Animator animator;
 
 
     NavMeshAgent agent;
 
     NavMeshAgent agent;
 +
    GameObject playerObj;
 
     void Start()
 
     void Start()
 
     {
 
     {
         animator = GetComponent<Animator>();
+
         playerObj = GameObject.Find("Player");
 +
        NavStart();
 +
    }
 +
    // 追跡ロジック開始
 +
    void NavStart()
 +
    {
 
         if (GetComponent<NavMeshAgent>() != null)
 
         if (GetComponent<NavMeshAgent>() != null)
 
         {
 
         {
行25: 行30:
 
     void Update()
 
     void Update()
 
     {
 
     {
         GameObject target = GameObject.Find("Main Camera");
+
         NavUpdate();
         if (target != null && agent != null)
+
    }
 +
    // 追跡ロジック
 +
    void NavUpdate()
 +
    {
 +
         if (playerObj != null && agent != null)
 
         {
 
         {
             agent.SetDestination(target.transform.position);
+
             agent.SetDestination(playerObj.transform.position);
 
         }
 
         }
 
     }
 
     }
行40: 行49:
 
==正面を向いて追跡==
 
==正面を向いて追跡==
 
<pre>
 
<pre>
public Transform target;
+
GameObject playerObj;
public float speed = 0.1f;
+
float speed = 0.1f;
 
void Start () {
 
void Start () {
     target = GameObject.Find("Target").transform;
+
     playerObj = GameObject.Find("Player");
 
}
 
}
 
void Update() {
 
void Update() {
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position - transform.position), 0.3f);
+
    transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(playerObj.transform.position - transform.position), 0.3f);
        transform.position += transform.forward * speed;
+
    transform.position += transform.forward * speed;
 
}
 
}
 
</pre>
 
</pre>
 
参考:https://qiita.com/ganbaru/items/d4fe649370ce4451db80
 
参考:https://qiita.com/ganbaru/items/d4fe649370ce4451db80
 +
 +
接触判定させる場合で、追いついて回転して、接触判定しないときはRigidbodyが足りないのかも・・
 +
 +
==NavMeshAgent同士の接触==
 +
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時点における最新版

追跡アクション追加

  1. 敵オブジェクトにAddComponentsでRigidbodyとCapsuleColliderを追加
  2. 床オブジェクトの(名前の横にある)staticにチェックをつける
  3. Unityメインメニュー/Window/AI/Navigationから床オブジェクトを選択し、Bakeタブを選択しBakeボタンを押す。
  4. 敵オブジェクトのAddComponentsからNavMeshAgentを追加
  5. 敵オブジェクトに以下csのようにNavMeshAgentを追加
  6. 障害物オブジェクトを設置してstaticにチェックを入れる。
  7. 障害物オブジェクトにも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同士の接触

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;
}

参考

https://unity.moon-bear.com/3d%E3%83%9B%E3%83%A9%E3%83%BC%E3%82%B2%E3%83%BC%E3%83%A0%E3%80%8C%E3%82%B9%E3%82%B1%E3%82%A2%E3%82%AF%E3%83%AD%E3%82%A6%EF%BC%9A%E5%BB%83%E6%9D%91%E3%81%AE%E6%81%90%E6%80%96%E3%80%8D/navmesh%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%80%8C%E8%BF%BD%E3%81%84%E3%81%8B%E3%81%91%E3%81%A6%E3%81%8F%E3%82%8B%E6%95%B5%E3%82%AD%E3%83%A3%E3%83%A9%E3%80%8D%E3%82%92%E4%BD%9C%E3%82%8B/

https://qiita.com/aimy-07/items/d1fea617ab9cbb3bd1ed