public Vector3 CheckPosition(Vector3 _position, float _range, LayerMask _mask) { Collider[] _colliders = Physics.OverlapSphere(_position, _range, _mask); int i = 0; while (i < _colliders.Length) { Collider _collider = _colliders[i]; if (_collider != null) { // try to get the closest point but this could fail for some reasons ... Vector3 _point = _collider.ClosestPointOnBounds(_position); // ... so compare the points and try to get the closest point on another way ... if (_point == _position) { _point = SystemTools.ClosestPointOnSurface(_collider, _position); } if (_point == _position) { _point = _collider.transform.position; } _position += (_position - _point).normalized * (PositionTools.Distance(_position, _point) + _range); } i++; } return(_position); }
public WaypointObject GetWaypointByPosition(Vector3 _position) { WaypointObject new_waypoint = null; int new_waypoint_index = m_WaypointIndex; float distance = Mathf.Infinity; List <WaypointObject> _waypoints = GetEnabledWaypoints(); for (int i = 0; i < _waypoints.Count; i++) { float tmp_distance = PositionTools.Distance(_position, _waypoints[i].TargetOffsetPosition); if (tmp_distance < distance) { new_waypoint_index = i; new_waypoint = _waypoints[new_waypoint_index]; distance = tmp_distance; } } if (new_waypoint != null) { m_LastWaypoint = m_Waypoint; m_Waypoint = new_waypoint; m_WaypointIndex = new_waypoint_index; } return(m_Waypoint); }
/// <summary> /// Gets the nearest focused entity by the specified type. /// </summary> /// <returns>The nearest focused entity by type.</returns> /// <param name="_type">Type.</param> /// <param name="_allow_child">If set to <c>true</c> allow child.</param> public ICECreatureEntity GetBestCounterpartByType(EntityClassType _type, int _max_counterparts, bool _allow_child = false) { ICECreatureEntity _best_entity = null; float _best_distance = Mathf.Infinity; int _best_counterparts = _max_counterparts; // transform buffer Transform _transform = this.transform; for (int i = 0; i < ActiveCounterparts.Count; i++) { ICECreatureEntity _entity = ActiveCounterparts[i]; if (_entity != null && _entity.EntityType == _type) { Transform _entity_transform = _entity.transform; int _entity_counterparts = _entity.ActiveCounterparts.Count; float _entity_distance = PositionTools.Distance(_transform.position, _entity_transform.position); if ((_entity_distance <= _best_distance) && (_allow_child || _entity_transform.IsChildOf(_transform) == false) && (_best_counterparts == -1 || _entity_counterparts <= _best_counterparts)) { _best_counterparts = _entity_counterparts; _best_distance = _entity_distance; _best_entity = _entity; } } } return(_best_entity); }
/// <summary> /// Gets the nearest focused entity. /// </summary> /// <returns>The nearest focused entity.</returns> /// <param name="_allow_child">If set to <c>true</c> allow child.</param> public ICECreatureEntity GetNearestActiveCounterparts(bool _allow_child = false) { ICECreatureEntity _best_entity = null; float _best_distance = Mathf.Infinity; // transform buffer Transform _transform = this.transform; for (int i = 0; i < ActiveCounterparts.Count; i++) { ICECreatureEntity _entity = ActiveCounterparts[i]; if (_entity != null) { // transform buffer Transform _entity_transform = _entity.transform; float _distance = PositionTools.Distance(_transform.position, _entity_transform.position); if (_distance < _best_distance) { if (_allow_child || _entity_transform.IsChildOf(_transform) == false) { _best_distance = _distance; _best_entity = _entity; } } } } return(_best_entity); }
/// <summary> /// Update the turret incl. movements and scan for targets /// </summary> public bool Update() { if (Owner == null) { return(false); } Scan(); m_IsFocused = false; m_IsMoving = false; // runs the default behaviour if there is no target if (m_ActiveTarget == null) { if (UseParkPosition) { if (PivotType == MountingPivotType.PivotalPoint) { PivotPoint.rotation = Quaternion.Slerp(PivotPoint.rotation, DefaultPivotRotation, RotationSpeed * Time.deltaTime); if (Quaternion.Angle(PivotPoint.rotation, DefaultPivotRotation) > MaxAngularDeviation) { m_IsMoving = true; } } else if (PivotType == MountingPivotType.SeperateAxes) { if (PivotYawAxis != null) { if (PositionTools.Distance(PivotYawAxis.localEulerAngles, new Vector3(0, DefaultPivotYawRotation, 0)) > MaxAngularDeviation) { PivotYawAxis.localEulerAngles = new Vector3(0, Mathf.LerpAngle(PivotYawAxis.localEulerAngles.y, DefaultPivotYawRotation, RotationSpeed * Time.deltaTime), 0); m_IsMoving = true; } else { PivotYawAxis.localEulerAngles = new Vector3(0, DefaultPivotYawRotation, 0); } } if (PivotPitchAxis != null) { if (PositionTools.Distance(PivotPitchAxis.localEulerAngles, new Vector3(DefaultPivotPitchRotation, 0, 0)) > MaxAngularDeviation) { PivotPitchAxis.localEulerAngles = new Vector3(Mathf.LerpAngle(PivotPitchAxis.localEulerAngles.x, DefaultPivotPitchRotation, RotationSpeed * Time.deltaTime), 0, 0); m_IsMoving = true; } else { PivotPitchAxis.localEulerAngles = new Vector3(DefaultPivotPitchRotation, 0, 0); } } } } } // focus an existing target else { float _height = 1; Collider _collider = m_ActiveTarget.GetComponent <Collider>(); if (_collider != null) { _height = _collider.bounds.size.magnitude / 3; } _height += VerticalTargetAdjustment; Vector3 _target_pos = m_ActiveTarget.position + (Vector3.up * _height); if (PivotType == MountingPivotType.PivotalPoint) { Quaternion _rotation = Quaternion.LookRotation(_target_pos - PivotPoint.position, Vector3.up); PivotPoint.rotation = Quaternion.Slerp(PivotPoint.rotation, _rotation, RotationSpeed * Time.deltaTime); if (Quaternion.Angle(PivotPoint.rotation, _rotation) < MaxAngularDeviation) { m_IsFocused = true; m_IsMoving = false; } else { m_IsFocused = false; m_IsMoving = true; } } else if (PivotType == MountingPivotType.SeperateAxes) { if (PivotYawAxis != null) { Vector3 _yaw_pos = new Vector3(_target_pos.x, PivotYawAxis.position.y, _target_pos.z); Quaternion _yaw_rot = Quaternion.LookRotation(_yaw_pos - PivotYawAxis.position, Vector3.up); PivotYawAxis.rotation = Quaternion.Slerp(PivotYawAxis.rotation, _yaw_rot, RotationSpeed * Time.deltaTime); if (Quaternion.Angle(PivotYawAxis.rotation, _yaw_rot) <= MaxAngularDeviation) { m_IsFocused = true; m_IsMoving = false; } else { m_IsFocused = false; m_IsMoving = true; } } if (PivotPitchAxis != null) { Vector3 _pitch_dir = PivotPitchAxis.position - _target_pos; Vector3 _pitch_hor = new Vector3(_pitch_dir.x, 0, _pitch_dir.z); float _angle = MathTools.NormalizeAngle(360 + Vector3.Angle(_pitch_dir, _pitch_hor) * Mathf.Sign(Vector3.Dot(_pitch_dir, Vector3.up))); PivotPitchAxis.localEulerAngles = new Vector3(Mathf.LerpAngle(PivotPitchAxis.localEulerAngles.x, _angle, RotationSpeed * Time.deltaTime), 0, 0); if (m_IsFocused && PositionTools.Distance(PivotPitchAxis.localEulerAngles, new Vector3(_angle, 0, 0)) <= MaxAngularDeviation) { m_IsFocused = true; m_IsMoving = false; } else { m_IsFocused = false; m_IsMoving = true; } } } } if (m_IsMoving) { MovingSound.Play(); } else { MovingSound.Stop(); } return(m_IsFocused); }
//private Quaternion m_MoveRotation; //private float m_MoveAngle = 0; /// <summary> /// DoUpdateMovePosition can be used to override the default move position of a creature. This delegated method will be called on each frame update /// </summary> /// <param name="_sender">Sender.</param> /// <param name="_origin_position">Origin position.</param> /// <param name="_new_position">New position.</param> private void DoUpdateMovePosition(GameObject _sender, Vector3 _transform_position, ref Vector3 _new_move_position) { // just to make sure that all required objects are available if (Controller == null || Controller.Creature.ActiveTarget == null || Controller.Creature.Move.TargetMovePositionReached) { return; } // the active target move position is the final destination the creature have to reach Vector3 _target_move_position = Controller.Creature.ActiveTargetMovePosition; // this will adapt the target move position to the grid Vector3 _grid_target_move_position = GetGridPosition(_target_move_position); // here we apapt the level of the new move position m_GridMovePosition.y = transform.position.y; // if the creature is near to the given node point we have to generate the next one if (PositionTools.Distance(m_GridMovePosition, transform.position) < Controller.Creature.Move.DesiredStoppingDistance) { // direction to the original target move position of the active target Vector3 _dir = (_target_move_position - transform.position).normalized; // here we get the next grid position according to the direction and the specified grid size Vector3 _next_grid_pos = GetGridPosition(transform.position + (_dir * GridSize)); // We do not want to allow diagonal movements, so we have to adjust all the paths that are longer than the grid size. if (PositionTools.Distance(m_GridMovePosition, _next_grid_pos) > GridSize + Controller.Creature.Move.DesiredStoppingDistance) { // ... in this case the selection of the direction will be done by chance if (UnityEngine.Random.Range(0, 1) == 0) { _next_grid_pos.x = m_GridMovePosition.x; } else { _next_grid_pos.z = m_GridMovePosition.z; } } // we take the new position only if this is closer to the target than the current one //if( ( _next_grid_pos - _grid_target_move_position ).magnitude < ( m_GridMovePosition - _grid_target_move_position ).magnitude ) m_GridMovePosition = _next_grid_pos; m_GridMoveRotation = Quaternion.LookRotation((m_GridMovePosition - transform.position).normalized); } else { // this code block makes sure that a creature is always on the grid float _speed = (Controller.Creature.Move.DesiredVelocity.z > 0 ? Controller.Creature.Move.DesiredVelocity.z : 1) * Time.deltaTime; Vector3 _move_direction = (m_GridMovePosition - transform.position); if (Mathf.Abs(_move_direction.x) < Mathf.Abs(_move_direction.z)) { transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x + _move_direction.x, transform.position.y, transform.position.z), _speed); } else if (Mathf.Abs(_move_direction.z) < Mathf.Abs(_move_direction.x)) { transform.position = Vector3.Lerp(transform.position, new Vector3(transform.position.x, transform.position.y, transform.position.z + _move_direction.z), _speed); } } // here we finally override the default move position of the creature _new_move_position = m_GridMovePosition; }
public Vector3 Scan(Transform _transform, Vector3 _position, LayerMask _ground_mask, LayerMask _water_mask, float _offset) { if (ScanningRange == 0 || ScanningAngle == 0 || (!UseSlopeLimits && !AvoidWater)) { return(_position); } if (Owner == null) { SetOwner(_transform.gameObject); } RaycastHit _hit; Vector3 _pos = PositionTools.GetDirectionPosition(_transform, 0, ScanningRange); _offset += m_VerticalRaycastOffset + ScanningRange; _pos.y += _offset; if (UseSlipping && MaxSurfaceSlopeAngle > 0) { if (Physics.Raycast(_transform.position + Vector3.up, Vector3.down, out _hit, Mathf.Infinity, _ground_mask, WorldManager.TriggerInteraction)) { if (Mathf.Abs(Vector3.Angle(_hit.normal, Vector3.up)) > MaxSurfaceSlopeAngle) { m_SlopePathPosition = Vector3.zero; _transform.position += new Vector3(_hit.normal.x * 9.8f * Time.deltaTime, 0, _hit.normal.z * 9.8f * Time.deltaTime); return(_position); } } } if (m_SlopePathPosition == Vector3.zero || PositionTools.Distance(_transform.position, m_SlopePathPosition) < ScanningRange * 0.25f) { LayerMask _combined_mask = _ground_mask; if (_water_mask.value != 0) { _combined_mask |= _water_mask; } if (Physics.Raycast(_pos, Vector3.down, out _hit, Mathf.Infinity, _combined_mask, WorldManager.TriggerInteraction)) { Vector3 _dir = (_hit.point - _transform.position).normalized; float _path_angle = Vector3.Angle(_dir, Vector3.down) - 90; float _surface_angle = Vector3.Angle(_hit.normal, Vector3.up); if ((MaxSurfaceSlopeAngle > 0 && Mathf.Abs(_surface_angle) > MaxSurfaceSlopeAngle) || (MaxPathSlopeAngle > 0 && Mathf.Abs(_path_angle) > MaxPathSlopeAngle) || (AvoidWater && SystemTools.IsInLayerMask(_hit.transform.gameObject, _water_mask))) { DebugLine(_hit.point, _hit.point + (Vector3.up * 2), Color.yellow); for (int i = ScanningAngle; i <= 180; i += ScanningAngle) { Vector3 _pos_right = Vector3.zero; Vector3 _pos_left = Vector3.zero; int _right_angle = i; _pos = PositionTools.GetDirectionPosition(_transform, _right_angle, ScanningRange); _pos.y += _offset; if (Physics.Raycast(_pos, Vector3.down, out _hit, Mathf.Infinity, _combined_mask, WorldManager.TriggerInteraction)) { _dir = (_hit.point - _transform.position).normalized; _path_angle = Vector3.Angle(_dir, Vector3.down) - 90; _surface_angle = Vector3.Angle(_hit.normal, Vector3.up); bool _walkable_right = true; bool _water = false; if (MaxSurfaceSlopeAngle > 0 && Mathf.Abs(_surface_angle) > MaxSurfaceSlopeAngle) { _walkable_right = false; } if (MaxPathSlopeAngle > 0 && _walkable_right && Mathf.Abs(_path_angle) > MaxPathSlopeAngle) { _walkable_right = false; } if (AvoidWater && SystemTools.IsInLayerMask(_hit.transform.gameObject, _water_mask)) { _walkable_right = false; _water = true; } if (DebugRayIsEnabled) { float _h = (MaxPathSlopeAngle > 0 ? MathTools.Normalize(MaxPathSlopeAngle - Mathf.Abs(_path_angle), 0, MaxPathSlopeAngle) : MathTools.Normalize(MaxSurfaceSlopeAngle - _surface_angle, 0, MaxSurfaceSlopeAngle)); //DebugLine( _pos, _hit.point, ( _water ? Color.blue : ( _walkable_right ? Color.green : new HSBColor( _h * 0.3333333f, 1f, 1f ).ToColor() ) ) ); DebugLine(_hit.point, _hit.point + (Vector3.up * 2), (_water ? Color.blue : (_walkable_right ? Color.green : new HSBColor(_h * 0.3333333f, 1f, 1f).ToColor()))); } if (_walkable_right) { _pos_right = _hit.point; } } else { m_VerticalRaycastOffset += 0.25f; } int _left_angle = 360 - i; _pos = PositionTools.GetDirectionPosition(_transform, _left_angle, ScanningRange); _pos.y += _offset; if (Physics.Raycast(_pos, Vector3.down, out _hit, Mathf.Infinity, _combined_mask, WorldManager.TriggerInteraction)) { _dir = (_hit.point - _transform.position).normalized; _path_angle = Vector3.Angle(_dir, Vector3.down) - 90; _surface_angle = Vector3.Angle(_hit.normal, Vector3.up); bool _walkable_left = true; bool _water = false; if (MaxSurfaceSlopeAngle > 0 && Mathf.Abs(_surface_angle) > MaxSurfaceSlopeAngle) { _walkable_left = false; } if (MaxPathSlopeAngle > 0 && _walkable_left && Mathf.Abs(_path_angle) > MaxPathSlopeAngle) { _walkable_left = false; } if (AvoidWater && SystemTools.IsInLayerMask(_hit.transform.gameObject, _water_mask)) { _walkable_left = false; _water = true; } if (DebugRayIsEnabled) { float _h = (MaxPathSlopeAngle > 0 ? MathTools.Normalize(MaxPathSlopeAngle - Mathf.Abs(_path_angle), 0, MaxPathSlopeAngle) : MathTools.Normalize(MaxSurfaceSlopeAngle - _surface_angle, 0, MaxSurfaceSlopeAngle)); //DebugLine( _pos, _hit.point, ( _water ? Color.blue : ( _walkable_left ? Color.green : new HSBColor( _h * 0.3333333f, 1f, 0.25f ).ToColor() ) ) ); DebugLine(_hit.point, _hit.point + (Vector3.up * 2), (_water ? Color.blue : (_walkable_left ? Color.green : new HSBColor(_h * 0.3333333f, 1f, 1f).ToColor()))); } if (_walkable_left) { _pos_left = _hit.point; } } else { m_VerticalRaycastOffset += 0.25f; } if (_pos_right != Vector3.zero && _pos_left != Vector3.zero) { //if( Vector3.Distance( _position, _pos_right ) <= Vector3.Distance( _position, _pos_left ) ) if (UnityEngine.Random.Range(0, 2) == 0) { m_SlopePathPosition = _pos_right; } else { m_SlopePathPosition = _pos_left; } break; } else if (_pos_right != Vector3.zero) { m_SlopePathPosition = _pos_right; break; } else if (_pos_left != Vector3.zero) { m_SlopePathPosition = _pos_left; break; } } } else { m_SlopePathPosition = Vector3.zero; if (DebugRayIsEnabled) { float _h = (MaxPathSlopeAngle > 0 ? MathTools.Normalize(MaxPathSlopeAngle - Mathf.Abs(_path_angle), 0, MaxPathSlopeAngle) : MathTools.Normalize(MaxSurfaceSlopeAngle - _surface_angle, 0, MaxSurfaceSlopeAngle)); DebugLine(_pos, _hit.point + (Vector3.up * 2), new HSBColor(_h * 0.3333333f, 1f, 0.25f).ToColor()); DebugLine(_hit.point, _hit.point + (Vector3.up * 2), new HSBColor(_h * 0.3333333f, 1f, 1f).ToColor()); } } } else { m_VerticalRaycastOffset += 0.25f; } } if (m_SlopePathPosition != Vector3.zero) { DebugLine(m_SlopePathPosition, m_SlopePathPosition + (Vector3.up * 2), Color.green); _position = m_SlopePathPosition; } return(_position); }
public Vector3 Scan(Transform _transform, Vector3 _position, LayerMask _mask, float _stopping_distance, float _speed) { if ((!UseDynamicScanningRange && ScanningRange == 0) || (UseDynamicScanningRange && _speed == 0)) { return(_position); } if (Time.time - m_StartTime <= m_ExpectedActionTime) { return(_position); } m_ActionType = ObstacleAvoidanceActionType.None; m_StoppingDistance = _stopping_distance; if (Owner != _transform.gameObject) { SetOwner(_transform.gameObject); } float _vertical_offset = 0; Vector3 _avoid_position = _position; Vector3 _transform_pos = _transform.position; Vector3 _move_pos = _position; float _distance = (UseDynamicScanningRange ? _speed * DynamicScanningRangeSpeedMultiplier : ScanningRange); _transform_pos.y = _transform_pos.y + _vertical_offset; _move_pos.y = _transform_pos.y; RaycastHit _hit; RaycastHit _hit_up = new RaycastHit(); RaycastHit _hit_down = new RaycastHit(); Vector3 _desired_dir = _position - _transform.position; Vector3 _origin = _transform.position + (_transform.up * VerticalRaycastOffset); Vector3 _origin_up = _transform.position + (_transform.up * (VerticalRaycastOffset + VerticalRaycastOffsetDifference)); // TODO : slide height Vector3 _origin_down = _transform.position + (_transform.up * (VerticalRaycastOffset - VerticalRaycastOffsetDifference)); // TODO : slide height Vector3 _forward = _transform.forward; float _cross_down_distance = (UseCrossBelowSpeed ? _speed * CrossBelowStartDistanceSpeedMultiplier : CrossBelowStartDistance); float _cross_up_distance = (UseCrossOverSpeed ? _speed * CrossOverStartDistanceSpeedMultiplier : CrossOverStartDistance); float _hit_down_distance = Mathf.Infinity; float _hit_up_distance = Mathf.Infinity; m_CrossBelowPossible = false; m_CrossOverPossible = false; if (UseOvercomeObstacles && Physics.Raycast(_origin_down, _forward, out _hit_down, _distance, _mask, WorldManager.TriggerInteraction) && !_hit_down.transform.IsChildOf(_transform)) { DebugLine(_origin_down, _hit_down.point, Color.red); DebugRay(_origin_down, _forward * _cross_down_distance, Color.blue); _hit_down_distance = _hit_down.distance; m_CrossBelowPossible = true; } else if (UseOvercomeObstacles) { DebugRay(_origin_down, _forward * _distance, Color.green); } if (UseOvercomeObstacles && Physics.Raycast(_origin_up, _forward, out _hit_up, _distance, _mask, WorldManager.TriggerInteraction) && !_hit_up.transform.IsChildOf(_transform)) { DebugLine(_origin_up, _hit_up.point, Color.red); DebugRay(_origin_up, _forward * _cross_up_distance, Color.blue); _hit_up_distance = _hit_up.distance; m_CrossOverPossible = true; } else if (UseOvercomeObstacles) { DebugRay(_origin_up, _forward * _distance, Color.green); } // CHECK POSIBLE CROSS OVER if (UseOvercomeObstacles && _hit_down_distance < _hit_up_distance) { if (_hit_down.distance < _cross_up_distance) { m_DesiredCrossOverPosition = _hit_down.point; m_DesiredCrossOverPosition.y = _hit_down.collider.bounds.center.y + 0.5f * Owner.GetComponent <Collider>().bounds.extents.y + 0.075f; m_StartTime = Time.time; m_ExpectedActionTime = _cross_up_distance * 2 / (_speed > 0 ? _speed : 1); m_ActionType = ObstacleAvoidanceActionType.CrossOver; } } // CHECK POSIBLE CROSS BELOW else if (UseOvercomeObstacles && _hit_up_distance < _hit_down_distance) { if (_hit_up.distance < _cross_down_distance) { m_DesiredCrossBelowPosition = _position + (1.25f * _hit_up.distance * _forward); m_StartTime = Time.time; m_ExpectedActionTime = _cross_down_distance * 2 / (_speed > 0 ? _speed : 1); m_ActionType = ObstacleAvoidanceActionType.CrossBelow; } } // CHECK AVOIDANCE else if (Physics.Raycast(_origin, _forward, out _hit, _distance, _mask, WorldManager.TriggerInteraction)) { if (!_hit.transform.IsChildOf(_transform)) { DebugLine(_origin, _hit.point, Color.red); if (_desired_dir.magnitude < PositionTools.Distance(_hit.point, _transform.position)) { DebugLine(_origin, _desired_dir, Color.green); m_ObstacleAvoidancePosition = Vector3.zero; m_FixDirection = PreferedDirectionType.UNDEFINED; } else { if (_distance > _hit.collider.bounds.size.magnitude * 0.5f) { _distance = _hit.collider.bounds.size.magnitude * 0.5f; } else if (_distance > new Vector2(_hit.collider.bounds.size.z, _hit.collider.bounds.size.x).magnitude) { _distance = new Vector2(_hit.collider.bounds.size.z, _hit.collider.bounds.size.x).magnitude; } DebugLine(_origin, _hit.point, Color.red); int _cost_right = 0; Vector3 _avoid_right = Vector3.zero; for (int i = ScanningAngle; i <= 360; i += ScanningAngle) { _cost_right++; Vector3 _pos = PositionTools.GetDirectionPosition(_transform, i, _distance); if (!Physics.Linecast(_origin, _pos, _mask)) { _avoid_right = _pos; DebugLine(_origin, _pos, SystemTools.ColorA(Color.blue, 0.5f)); break; } else { //TODO: if there is no free position we could determinate the best posibility DebugLine(_origin, _pos, SystemTools.ColorA(Color.red, 0.25f)); } } int _cost_left = 0; Vector3 _avoid_left = Vector3.zero; for (int i = 360 - ScanningAngle; i > 0; i -= ScanningAngle) { _cost_left++; Vector3 _pos = PositionTools.GetDirectionPosition(_transform, i, _distance); if (!Physics.Linecast(_origin, _pos, _mask)) { _avoid_left = _pos; DebugLine(_origin, _pos, SystemTools.ColorA(Color.blue, 0.5f)); break; } else { //TODO: if there is no free position we could determinate the best posibility DebugLine(_origin, _pos, SystemTools.ColorA(Color.red, 0.25f)); } } // selects the best solution according to the given costs if (_avoid_right != Vector3.zero && _avoid_left != Vector3.zero) { if (_cost_left < _cost_right) { m_ObstacleAvoidancePosition = _avoid_left; } else if (_cost_right < _cost_left) { m_ObstacleAvoidancePosition = _avoid_right; } else { m_ObstacleAvoidancePosition = (Random.Range(0, 1) == 1 ? _avoid_left : _avoid_right); } } else if (_avoid_right != Vector3.zero) { m_ObstacleAvoidancePosition = _avoid_right; } else if (_avoid_left != Vector3.zero) { m_ObstacleAvoidancePosition = _avoid_left; } // makes sure that the creature will not change the direction if not needed if (UseFixDirection) { if (m_FixDirection == PreferedDirectionType.UNDEFINED) { if (m_ObstacleAvoidancePosition == _avoid_right) { m_FixDirection = PreferedDirectionType.RIGHT; } else if (m_ObstacleAvoidancePosition == _avoid_left) { m_FixDirection = PreferedDirectionType.LEFT; } } else if (m_FixDirection == PreferedDirectionType.RIGHT && _avoid_right != Vector3.zero) { m_ObstacleAvoidancePosition = _avoid_right; } else if (m_FixDirection == PreferedDirectionType.LEFT && _avoid_left != Vector3.zero) { m_ObstacleAvoidancePosition = _avoid_left; } } } } } else { DebugRay(_origin, _forward * _distance, Color.green); m_FixDirection = PreferedDirectionType.UNDEFINED; if (Physics.Raycast(_origin, _desired_dir, out _hit, _distance, _mask, WorldManager.TriggerInteraction)) { DebugLine(_origin, _hit.point, SystemTools.ColorA(Color.red, MathTools.Normalize(_distance - PositionTools.Distance(_hit.point, _origin), 0, _distance))); if (AvoidanceMovePositionReached) { m_ObstacleAvoidancePosition = _transform.position + (_transform.forward * _distance); } } else { DebugRay(_origin, _desired_dir.normalized * _distance, Color.gray); m_ObstacleAvoidancePosition = Vector3.zero; } } if (m_ObstacleAvoidancePosition != Vector3.zero) { _avoid_position = m_ObstacleAvoidancePosition; } return(_avoid_position); }
/// <summary> /// SendDamage handles damage and impact forces for the specified target object. You can use this static method to /// affect each entity object within your scene. Please note that _target can be adjusted to null, in /// such a case the _force_type will be automatically changed to DamageForceType.Explosion and the origin /// of the detonation will be the _sender.transform.position. /// </summary> /// <param name="_sender">Sender.</param> /// <param name="_target">Target.</param> /// <param name="_impact_type">Impact type.</param> /// <param name="_damage">Damage.</param> /// <param name="_damage_method">Damage method.</param> /// <param name="_damage_point">Damage point.</param> /// <param name="_force_type">Force type.</param> /// <param name="_force">Force.</param> /// <param name="_radius">Radius.</param> public static void SendDamage(GameObject _sender, GameObject _target, DamageTransferType _impact_type, float _damage, string _damage_method, Vector3 _damage_point, DamageForceType _force_type, float _force, float _radius) { if (_sender == null) { return; } if (_target == null) { _force_type = DamageForceType.Explosion; } // If the force type is an explosion will will handle first the explosion impact to all objects around the specified target // in cases the target will be NULL (e.g. remote or timed detonation of an explosive etc.) the sender will be the origin of // the explosion. if (_force_type == DamageForceType.Explosion) { _damage_point = (_damage_point == Vector3.zero ? (_target != null ? _target.transform.position : _sender.transform.position) : _damage_point); Collider[] _colliders = Physics.OverlapSphere(_damage_point, _radius); if (_colliders != null) { foreach (Collider _collider in _colliders) { if (_collider == null || _collider.gameObject == _target || _collider.gameObject == _sender) { continue; } float _distance = PositionTools.Distance(_damage_point, _collider.gameObject.transform.position); float _multiplier = Mathf.Clamp01(1 - MathTools.Normalize(_distance, 0, _radius)); // If a explosion radius is given we will try to apply a suitable force to the colliders gamesobject if (_radius > 0) { if (_collider.attachedRigidbody != null && !_collider.attachedRigidbody.isKinematic) { _collider.attachedRigidbody.AddExplosionForce(_force * _multiplier, _damage_point, _radius); } else { ICEWorldEntity _entity = ICEWorldEntity.GetWorldEntity(_collider.gameObject); if (_entity != null) { Vector3 _direction = _collider.transform.position - _damage_point; _entity.ApplyImpact(_direction, _force * _multiplier); } } } // SendTargetDamage will try now to damage the colliders gameobject according to the given distance and multiplier ICEWorldEntity.SendTargetDamage(_sender, _collider.gameObject, _impact_type, _damage * _multiplier, _damage_method, _damage_point, _force_type, _force * _multiplier); } } } if (_target != null) { // whenever a target is specified and the defined force type isn't NONE we try to apply also a force to the target if (_force_type != DamageForceType.None) { Vector3 _direction = _target.transform.position - _sender.transform.position; _direction.Normalize(); // Handle Target Rigidbody and forces Rigidbody _target_rigidbody = _target.GetComponent <Rigidbody>(); if (_target_rigidbody != null && !_target_rigidbody.isKinematic) { _target_rigidbody.AddForce(_direction.normalized * _force, ForceMode.Force); } else { ICEWorldEntity _entity = ICEWorldEntity.GetWorldEntity(_target); if (_entity != null) { _entity.ApplyImpact(_direction, _force); } } } // Finally we try to damage the specified target ICEWorldEntity.SendTargetDamage(_sender, _target, _impact_type, _damage, _damage_method, _damage_point, _force_type, _force); } }
public bool Check(Transform _transform, Vector3 _velocity) { if (!Enabled || _transform == null) { return(false); } if (_velocity.z == 0) { m_DeadlockMoveTimer = 0; m_DeadlockLoopTimer = 0; return(false); } m_DeadlockMoveTimer += Time.deltaTime; m_DeadlockLoopTimer += Time.deltaTime; if (m_DeadlockPosition == Vector3.zero) { m_DeadlockPosition = _transform.position; } if (m_DeadlockMoveTimer >= MoveInterval) { m_DeadlocksDistance = PositionTools.Distance(_transform.position, m_DeadlockPosition); // CHECK DEADLOCK if (m_DeadlocksDistance <= MinMoveDistance) { if (m_Deadlocked == false) { m_DeadlocksCount++; } m_DeadlocksCriticalPositions.Add(_transform.position); if (m_DeadlocksCriticalPositions.Count > MoveMaxCriticalPositions) { m_Deadlocked = true; } } else if (m_DeadlocksCriticalPositions.Count > 0) { m_DeadlocksCriticalPositions.RemoveAt(0); } else { m_DeadlockPosition = _transform.position; m_DeadlockMoveTimer = 0; } } // CHECK INFINITY LOOP if (m_DeadlockLoopTimer >= LoopInterval) { if (m_DeadlocksDistance <= LoopRange) { if (m_Deadlocked == false) { m_DeadlockLoopsCount++; } m_DeadlocksCriticalLoops.Add(_transform.position); if (m_DeadlocksCriticalLoops.Count > LoopMaxCriticalPositions) { m_Deadlocked = true; } } else if (m_DeadlocksCriticalLoops.Count > 0) { m_DeadlocksCriticalLoops.RemoveAt(0); } else { m_DeadlockLoopTimer = 0; } } if (m_DeadlockMoveTimer == 0 && m_DeadlocksCriticalPositions.Count == 0 && m_DeadlockLoopTimer == 0 && m_DeadlocksCriticalLoops.Count == 0) { m_Deadlocked = false; } return(m_Deadlocked); }
private bool IsTargetUpdatePermitted(TargetObject _target) { if (_target == null) { return(false); } if (m_ActiveTarget == null || Behaviour.ActiveBehaviourMode == null || Behaviour.ActiveBehaviourMode.Favoured.Enabled == false) { return(true); } bool _permitted = true; if ((Behaviour.ActiveBehaviourMode.Favoured.Enabled == true) && ( (Behaviour.ActiveBehaviourMode.Favoured.Runtime > 0 && Behaviour.BehaviourTimer < Behaviour.ActiveBehaviourMode.Favoured.Runtime) || (Behaviour.ActiveBehaviourMode.Favoured.FavouredUntilNextMovePositionReached && !Move.MovePositionReached) || (Behaviour.ActiveBehaviourMode.Favoured.FavouredUntilTargetMovePositionReached && !Move.TargetMovePositionReached) || (Behaviour.ActiveBehaviourMode.Favoured.FavouredUntilNewTargetInRange(_target, PositionTools.Distance(_target.TargetGameObject.transform.position, Owner.transform.position))) || (Behaviour.ActiveBehaviourMode.HasActiveDetourRule && Behaviour.ActiveBehaviourMode.Favoured.FavouredUntilDetourPositionReached && !Move.DetourComplete))) { _permitted = false; } else { _permitted = true; } //mode check - the new mode could be also forced, so we have to check this here if (_permitted == false) { BehaviourModeObject _mode = Behaviour.GetBehaviourModeByKey(_target.Behaviour.CurrentBehaviourModeKey); if (_mode != null && _mode.Favoured.Enabled == true) { if (Behaviour.ActiveBehaviourMode.Favoured.FavouredPriority > _mode.Favoured.FavouredPriority) { _permitted = false; } else if (Behaviour.ActiveBehaviourMode.Favoured.FavouredPriority < _mode.Favoured.FavouredPriority) { _permitted = true; } else { _permitted = (Random.Range(0, 1) == 0?false:true); } } } return(_permitted); }