/// <summary> /// Gets the desired steering output. /// </summary> /// <param name="input">The steering input containing relevant information to use when calculating the steering output.</param> /// <param name="output">The steering output to be populated.</param> public override void GetDesiredSteering(SteeringInput input, SteeringOutput output) { _lastContainVector = Vector3.zero; if (input.grid == null) { // if off-grid, exit early return; } _unitData = input.unit; if (!_unitData.isGrounded) { // while in the air, exit early return; } // prepare local variables Vector3 selfPos = _unitData.position; Vector3 containVector = Vector3.zero; float selfHeight = _unitData.basePosition.y; // generate positions to the left and right Vector3 rightPos = selfPos + (Vector3.right * bufferDistance); Vector3 leftPos = selfPos + (Vector3.left * bufferDistance); float rightHeight, leftHeight; // sample left and right bool rightContain = _heightSampler.TrySampleHeight(rightPos, out rightHeight); bool leftContain = _heightSampler.TrySampleHeight(leftPos, out leftHeight); // if cell is missing or drop is more than allowed drop height or climb is more than allowed climb height, then compute an axis-aligned containment vector if (!rightContain || (selfHeight - rightHeight > _heightCaps.maxDropHeight) || (rightHeight - selfHeight > _heightCaps.maxClimbHeight)) { containVector = Vector3.left; } else if (!leftContain || (selfHeight - leftHeight > _heightCaps.maxDropHeight) || (leftHeight - selfHeight > _heightCaps.maxClimbHeight)) { containVector = Vector3.right; } // generate positions forward and backwards Vector3 forwardPos = selfPos + (Vector3.forward * bufferDistance); Vector3 backwardPos = selfPos + (Vector3.back * bufferDistance); float forwardHeight, backHeight; // sample forward and backwards bool forwardContain = _heightSampler.TrySampleHeight(forwardPos, out forwardHeight); bool backContain = _heightSampler.TrySampleHeight(backwardPos, out backHeight); // if cell is missing or drop is more than allowed drop height or climb is more than allowed climb height, then compute an axis-aligned containment vector if (!forwardContain || (selfHeight - forwardHeight > _heightCaps.maxDropHeight) || (forwardHeight - selfHeight > _heightCaps.maxClimbHeight)) { // we need to check whether containVector has a value beforehand, in which case we need to normalize containVector = containVector.sqrMagnitude != 0f ? (containVector + Vector3.back).normalized : Vector3.back; } else if (!backContain || (selfHeight - backHeight > _heightCaps.maxDropHeight) || (backHeight - selfHeight > _heightCaps.maxClimbHeight)) { // we need to check whether containVector has a value beforehand, in which case we need to normalize containVector = containVector.sqrMagnitude != 0f ? (containVector + Vector3.forward).normalized : Vector3.forward; } if (containVector.sqrMagnitude == 0f) { // no contain vectors to worry about - no containment necessary return; } // Containment vectors are always "full strength" Vector3 steeringVector = containVector * input.maxAcceleration; _lastContainVector = steeringVector; output.desiredAcceleration = steeringVector; }