blob: 0d4e22230ca7cae82af98af99e04d59e55574f5b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
using UnityEngine;
using System.Collections.Generic;
namespace BehaviorDesigner.Runtime.Tasks
{
[TaskDescription("Similar to the sequence task, the random sequence task will return success as soon as every child task returns success. " +
"The difference is that the random sequence class will run its children in a random order. The sequence task is deterministic " +
"in that it will always run the tasks from left to right within the tree. The random sequence task shuffles the child tasks up and then begins " +
"execution in a random order. Other than that the random sequence class is the same as the sequence class. It will stop running tasks " +
"as soon as a single task ends in failure. On a task failure it will stop executing all of the child tasks and return failure. " +
"If no child returns failure then it will return success.")]
[HelpURL("http://www.opsive.com/assets/BehaviorDesigner/documentation.php?id=31")]
[TaskIcon("{SkinColor}RandomSequenceIcon.png")]
public class RandomSequence : Composite
{
[Tooltip("Seed the random number generator to make things easier to debug")]
public int seed = 0;
[Tooltip("Do we want to use the seed?")]
public bool useSeed = false;
// A list of indexes of every child task. This list is used by the Fischer-Yates shuffle algorithm.
private List<int> childIndexList = new List<int>();
// The random child index execution order.
private Stack<int> childrenExecutionOrder = new Stack<int>();
// The task status of the last child ran.
private TaskStatus executionStatus = TaskStatus.Inactive;
public override void OnAwake()
{
// If specified, use the seed provided.
if (useSeed) {
Random.InitState(seed);
}
// Add the index of each child to a list to make the Fischer-Yates shuffle possible.
childIndexList.Clear();
for (int i = 0; i < children.Count; ++i) {
childIndexList.Add(i);
}
}
public override void OnStart()
{
// Randomize the indecies
ShuffleChilden();
}
public override int CurrentChildIndex()
{
// Peek will return the index at the top of the stack.
return childrenExecutionOrder.Peek();
}
public override bool CanExecute()
{
// Continue exectuion if no task has return failure and indexes still exist on the stack.
return childrenExecutionOrder.Count > 0 && executionStatus != TaskStatus.Failure;
}
public override void OnChildExecuted(TaskStatus childStatus)
{
// Pop the top index from the stack and set the execution status.
if (childrenExecutionOrder.Count > 0) {
childrenExecutionOrder.Pop();
}
executionStatus = childStatus;
}
public override void OnConditionalAbort(int childIndex)
{
// Start from the beginning on an abort
childrenExecutionOrder.Clear();
executionStatus = TaskStatus.Inactive;
ShuffleChilden();
}
public override void OnEnd()
{
// All of the children have run. Reset the variables back to their starting values.
executionStatus = TaskStatus.Inactive;
childrenExecutionOrder.Clear();
}
public override void OnReset()
{
// Reset the public properties back to their original values
seed = 0;
useSeed = false;
}
private void ShuffleChilden()
{
// Use Fischer-Yates shuffle to randomize the child index order.
for (int i = childIndexList.Count; i > 0; --i) {
int j = Random.Range(0, i);
int index = childIndexList[j];
childrenExecutionOrder.Push(index);
childIndexList[j] = childIndexList[i - 1];
childIndexList[i - 1] = index;
}
}
}
}
|