碰撞检测脚本有时会失败

时间:2017-08-25 14:33:27

标签: c# unity3d artificial-intelligence collision-detection path-finding

在大多数情况下,这个剧本有效,但是偶尔会有一个敌人在寻路时失败并穿过建筑物或墙壁。有没有办法可以阻止这个?

using UnityEngine;
using System.Collections;

namespace Daniel {
    public class EnemyAI : Living {

        // Detection private int range = 10; private float speed = 10f; private bool isThereAnyThing = false;

        // Waypoints/Targets
        public GameObject[] targets;
        private float rotationSpeed = 900f;
        private RaycastHit hit;
        GameObject target;
        [SerializeField]
        private int randomTarget = 0;
        [SerializeField]
        float timeToNextCheck = 3;
        public float effectTimer = 2f;
        public GameObject deathEffect;
        public LayerMask detectThis;

        void Start()
        {
            randomTarget = Random.Range(0, 8);
            target = targets[randomTarget];
        }
        void FixedUpdate()
        {
            timeToNextCheck = timeToNextCheck - Time.deltaTime;
            ScanForNewWaypoint();
            LookAtTarget();
            Move();
            CheckForObsticales();
        }
        void LookAtTarget()
        {
            //Look At Somthly Towards the Target if there is nothing in front.
            if (!isThereAnyThing)
            {
                Vector3 relativePos = target.transform.position - transform.position;
                Quaternion rotation = Quaternion.LookRotation(relativePos);
                transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime);
            }
        }
        void Move()
        {
            // Enemy translate in forward direction.
            transform.Translate(Vector3.forward * Time.deltaTime * speed);
        }
        public void CheckForObsticales()
        {
            //Checking for any Obstacle in front.
            // Two rays left and right to the object to detect the obstacle.
            Transform leftRay = transform;
            Transform rightRay = transform;
            //Use Phyics.RayCast to detect the obstacle
            if (Physics.Raycast(leftRay.position + (transform.right * 7f), transform.forward, out hit, range, detectThis) || Physics.Raycast(rightRay.position - (transform.right * 7f), transform.forward, out hit, range))
            {
                if (hit.collider.gameObject.CompareTag("Obstacles"))
                {
                    isThereAnyThing = true;
                    transform.Rotate(Vector3.up * Time.deltaTime * rotationSpeed);
                }
            }
            // Now Two More RayCast At The End of Object to detect that object has already pass the obsatacle.
            // Just making this boolean variable false it means there is nothing in front of object.
            if (Physics.Raycast(transform.position - (transform.forward * 4), transform.right, out hit, 10, detectThis) ||
                Physics.Raycast(transform.position - (transform.forward * 4), -transform.right, out hit, 10, detectThis))
            {
                if (hit.collider.gameObject.CompareTag("Obstacles"))
                {
                    isThereAnyThing = false;
                }
            }
        }
        public void ScanForNewWaypoint()
        {
            CheckForObsticales();
            if (timeToNextCheck <= 0)
            {
                timeToNextCheck = Random.Range(6, 3);
                randomTarget = Random.Range(0, 8);
                target = targets[randomTarget];
            }
        }
        public override void TakeHit(float dmg, Vector3 hitPoint, Vector3 hitDirection)
        {
            if (dmg >= health)
            {
                Destroy(Instantiate(deathEffect, hitPoint, Quaternion.FromToRotation(Vector3.forward, hitDirection)) as GameObject, effectTimer);
                Debug.Log("Exploded");
            }
            base.TakeHit(dmg, hitPoint, hitDirection);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

现在,这是人们在使用物理引擎时遇到的最常见问题之一,并且相信我有很多因素会影响您所面临的结果/后果。人们设计的最常见解决方案是使用更新 执行每一帧进行物理计算完全错误。所有与物理相关的计算都需要在固定更新内执行,否则在更新中执行基于物理的模拟将会过于昂贵,这意味着每一帧都是如此。如果您的 Enemy 正在经历墙壁并且物理碰撞缺失,您可以采取的最佳解决方案是调整Unity中的一些物理相关属性这些位于编辑&gt;&gt;&gt;项目设置&gt;&gt;&gt;时间更改检查器中的时间步长和最大允许时间步长,以便将碰撞设置为正确。在处理像尺度,质量和碰撞器等物理时,还要记住一些其他的事情。这里有一个Link关于统一物理设置的详细机制。在处理和调整物理设置之前,请务必阅读并理解链接的内容。