Combine Sequence + Success

xjjon

New member
Hi, I'm trying to implement a combined sequence (Composite) that always return success.

1622917027400.png

I frequently use this pattern and would like to combine it into 1 node.

C#:
        public override void OnChildExecuted(TaskStatus childStatus)
        {
            // Increase the child index and update the execution status after a child has finished running.
            currentChildIndex++;
            executionStatus = childStatus;

            if (AlwaysReturnTrue && childStatus == TaskStatus.Failure)
            {
                currentChildIndex = children.Count;
                executionStatus = TaskStatus.Success;
            }
        }

Which is used like this (AlwaysReturnTrue is set to true, so that the sequence SHOULD always be success even if the child fails.
However doesn't seem to work. If random probability returns Failure, the sequence still returns failure (even though executionStatus is forced to be Success)

1622916963300.png

Is there something behind the implementation that I'm missing? Maybe the execution status is propagated before `OnChildExecute` is called? If so, is there a better way to implement this composite?
 
If you override the Decorate method with your success return status then it should no longer return failure.
 
Thanks, that worked very well. It was unclear to me when I last looked at it as I had not looked at the Runtime Source. Now it's very clear.

Here's the snippet if anyone stumbles upon the same question:
Note the `ChildStatusAlwaysTrue` flag and changes in Decorate and OnChildExecuted. Everything else is the same as in Sequence.

This will skip the remaining tasks in the sequence when a child fails - but still return success. This avoids the need for an extra `Return Success` node.

C#:
[TaskIcon("{SkinColor}SequenceIcon.png")]
    public class CustomSequence : BehaviorDesigner.Runtime.Tasks.Composite
    {
        public bool ChildStatusAlwaysTrue = true;
        
        // The index of the child that is currently running or is about to run.
        private int currentChildIndex = 0;
        // The task status of the last child ran.
        private TaskStatus executionStatus = TaskStatus.Inactive;
        
        public override TaskStatus Decorate(TaskStatus status)
        {
            if (ChildStatusAlwaysTrue)
            {
                return TaskStatus.Success;
            }

            return status;
        }
        
        public override void OnChildExecuted(TaskStatus childStatus)
        {
            // Increase the child index and update the execution status after a child has finished running.
            currentChildIndex++;
            executionStatus = childStatus;
            
            if (ChildStatusAlwaysTrue && childStatus == TaskStatus.Failure)
            {
                // Skips remaining tasks the sequence
                currentChildIndex = children.Count;
            }
        }

        // No changes from Sequence below this line

        public override int CurrentChildIndex()
        {
            return currentChildIndex;
        }

        public override bool CanExecute()
        {
            // We can continue to execuate as long as we have children that haven't been executed and no child has returned failure.
            return currentChildIndex < children.Count && executionStatus != TaskStatus.Failure;
        }

        
        public override void OnConditionalAbort(int childIndex)
        {
            // Set the current child index to the index that caused the abort
            currentChildIndex = childIndex;
            executionStatus = TaskStatus.Inactive;
        }

        public override void OnEnd()
        {
            // All of the children have run. Reset the variables back to their starting values.
            executionStatus = TaskStatus.Inactive;
            currentChildIndex = 0;
        }
    }
 
Top