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