예제 #1
0
        public Vector3 Update(Transform _transform, LayerMask _mask, float _speed, bool _allow = true)
        {
            Vector3    _position = _transform.position;
            Quaternion _rotation = _transform.rotation;

            m_MoveRequired = false;
            m_IsBlocked    = false;

            if (OverlapPreventionType != OverlapType.NONE && _allow == true)
            {
                StoreTransformData(_transform);

                Vector3 _center = _transform.TransformPoint(Center);

                Collider[] _colliders = null;

#if UNITY_5_4_OR_NEWER
                Vector3 _end = _transform.TransformPoint(End);

                if (OverlapPreventionType == OverlapType.SPHERE)
                {
                    _colliders = Physics.OverlapSphere(_center, Radius, _mask);
                }
                else if (OverlapPreventionType == OverlapType.BOX)
                {
                    _colliders = Physics.OverlapBox(_center, Size / 2, _transform.rotation, _mask);
                }
                else if (OverlapPreventionType == OverlapType.CAPSULE)
                {
                    _colliders = Physics.OverlapCapsule(_center, _end, Radius, _mask);
                }
#elif UNITY_5_3 || UNITY_5_3_OR_NEWER
                if (OverlapPreventionType == OverlapType.BOX)
                {
                    _colliders = Physics.OverlapBox(_center, Size / 2, _transform.rotation, _mask);
                }
                else
                {
                    _colliders = Physics.OverlapSphere(_center, Radius, _mask);
                }
#else
                _colliders = Physics.OverlapSphere(_center, Radius, _mask);
#endif
                // this list will be used to handle multiple collisions
                //List<Vector3> _points = new List<Vector3>();

                float _last_angle = 0;

                int i = 0;
                while (i < _colliders.Length)
                {
                    Collider _collider = _colliders[i];

                    if (_collider != null && !_collider.gameObject.transform.IsChildOf(_transform))
                    {
                        // try to get the closest point but this could fail for some reasons ...
                        Vector3 _point = _collider.ClosestPointOnBounds(_transform.position);

                        // ... so compare the points and try to get the closest point on another way ...
                        if ((_point - _position).magnitude < 0.05f)
                        {
                            _point = SystemTools.ClosestPointOnSurface(_collider, _transform.position);                               ////SystemTools.NearestVertexTo( _collider.gameObject, _transform.position );
                        }
                        if ((_point - _position).magnitude < 0.01f)
                        {
                            _point = _collider.transform.position;
                        }

                        // this block will be used to handle multiple collisions

                        /*{
                         * // if we have found the closest point we will store it ...
                         * //if( _point != _transform.position )
                         * //	_points.Add( _point );
                         *
                         * // if we have more than two points we have to evaluate the center
                         * //if( _points.Count > 1 )
                         * //{
                         * //	_point = SystemTools.FindCenterPoint( _points.ToArray() );
                         *      //Debug.DrawRay( _point, Vector3.up * 20, Color.red );
                         * //		}
                         * }*/


                        //Debug.DrawLine( _transform.position, _point, Color.green );

                        Vector3 _heading   = PositionTools.OverGroundHeading(_transform.position, _point);
                        Vector3 _direction = PositionTools.Direction(_heading);

                        if (_direction == Vector3.zero)
                        {
                            _direction = _transform.forward;
                        }

                        float _angle = PositionTools.DirectionAngle(_transform.forward, _direction) * 180;

                        //PrintDebugLog( this, "OverlapPrevention Hit#" + i + " Position" + _transform.position + " HitPoint" + _point + " Heading" + _heading + " Direction" + _direction + " Angle = " + _angle );

                        // INFRONT - if the collision is infront of the object it will stop or try to avoid the collision object
                        if (Mathf.Abs(_angle) <= 90)
                        {
                            // if our object have to avoid the collision it will turn right or left and try to move around
                            if (UseAvoiding)
                            {
                                _last_angle += (_last_angle == 0 ? (_angle < 0 ? 90 : -90) : _last_angle);

                                Vector3 _avoid_direction = MathTools.RotateVectorFromTo(_transform.rotation, MathTools.AddRotation(_transform.rotation, new Vector3(0, _last_angle, 0)), _direction);
                                _rotation = Quaternion.Slerp(m_LastTransformRotation, Quaternion.LookRotation(_avoid_direction.normalized), AngularSpeed * Time.deltaTime);
                                _position = m_LastTransformPosition + (_avoid_direction.normalized * _speed * AvoidSpeedMultiplier * Time.deltaTime);
                            }

                            // if the object have to stop, it will  be replaced outside of the collision range or use its last position
                            else
                            {
                                if (_speed == 0)
                                {
                                    float _radius = Size.magnitude;
#if UNITY_5_4_OR_NEWER
                                    if (OverlapPreventionType == OverlapType.SPHERE || OverlapPreventionType == OverlapType.CAPSULE)
                                    {
                                        _radius = Radius;
                                    }
#else
                                    if (OverlapPreventionType == OverlapType.SPHERE)
                                    {
                                        _radius = Radius;
                                    }
#endif
                                    _point.y = _position.y;

                                    Vector3 _dir = _point - _position;

                                    _position = m_LastTransformPosition + _dir - (_dir.normalized * _radius);
                                }
                                else
                                {
                                    _position = m_LastTransformPosition;
                                }

                                _rotation   = m_LastTransformRotation;
                                m_IsBlocked = true;
                            }
                        }

                        // BEHIND - ... otherwise, if the collision is behind our object it can try to escape forwards while itsn't doing an avoid move
                        else if (_last_angle == 0)
                        {
                            if (m_LastTransformForward == Vector3.zero)
                            {
                                m_LastTransformForward = _transform.forward;
                            }

                            _rotation = Quaternion.Slerp(m_LastTransformRotation, Quaternion.LookRotation(m_LastTransformForward), AngularSpeed * Time.deltaTime);
                            _position = m_LastTransformPosition + (m_LastTransformForward * _speed * EscapeSpeedMultiplier * Time.deltaTime);
                        }

                        // UNCLEAR - ... in all other cases our object have to stop to avoid stuppid motions
                        else
                        {
                            float _radius = Size.magnitude;

#if UNITY_5_4_OR_NEWER
                            if (OverlapPreventionType == OverlapType.SPHERE || OverlapPreventionType == OverlapType.CAPSULE)
                            {
                                _radius = Radius;
                            }
#else
                            if (OverlapPreventionType == OverlapType.SPHERE)
                            {
                                _radius = Radius;
                            }
#endif

                            _point.y = _position.y;

                            Vector3 _dir = _point - _position;

                            _position   = m_LastTransformPosition + _dir - (_dir.normalized * _radius);
                            _rotation   = m_LastTransformRotation;
                            m_IsBlocked = true;
                        }
                    }
                    i++;
                }
            }



            if (_transform.position != _position)
            {
                _transform.position = _position;
            }

            if (_transform.rotation != _rotation)
            {
                _transform.rotation = _rotation;
            }

            m_LastTransformPosition = _transform.position;
            m_LastTransformRotation = _transform.rotation;
            m_LastTransformForward  = _transform.forward;


            return(_position);
        }